//
//  ========================================================================
//  Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.http;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jetty.http.MimeTypes.Type;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.resource.Resource;


/* ------------------------------------------------------------ */
/** HttpContent created from a {@link Resource}.
 * <p>The HttpContent is used to server static content that is not
 * cached. So fields and values are only generated as need be an not 
 * kept for reuse</p>
 */
public class ResourceHttpContent implements HttpContent
{
    final Resource _resource;
    final String _contentType;
    final int _maxBuffer;
    Map<CompressedContentFormat, HttpContent> _precompressedContents;
    String _etag;

    /* ------------------------------------------------------------ */
    public ResourceHttpContent(final Resource resource, final String contentType)
    {
        this(resource,contentType,-1,null);
    }

    /* ------------------------------------------------------------ */
    public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer)
    {
        this(resource,contentType,maxBuffer,null);
    }
    
    /* ------------------------------------------------------------ */
    public ResourceHttpContent(final Resource resource, final String contentType, int maxBuffer, Map<CompressedContentFormat, HttpContent> precompressedContents)
    {
        _resource=resource;
        _contentType=contentType;
        _maxBuffer = maxBuffer;
        if (precompressedContents == null)
        {
            _precompressedContents = null;
        }
        else
        {
            _precompressedContents = new HashMap<>(precompressedContents.size());
            for (Map.Entry<CompressedContentFormat, HttpContent> entry : precompressedContents.entrySet())
            {
                _precompressedContents.put(entry.getKey(),new PrecompressedHttpContent(this,entry.getValue(),entry.getKey()));
            }
        }
    }

    /* ------------------------------------------------------------ */
    @Override
    public String getContentTypeValue()
    {
        return _contentType;
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public HttpField getContentType()
    {
        return _contentType==null?null:new HttpField(HttpHeader.CONTENT_TYPE,_contentType);
    }

    /* ------------------------------------------------------------ */
    @Override
    public HttpField getContentEncoding()
    {
        return null;
    }

    /* ------------------------------------------------------------ */
    @Override
    public String getContentEncodingValue()
    {
        return null;
    }

    /* ------------------------------------------------------------ */
    @Override
    public String getCharacterEncoding()
    {
        return _contentType==null?null:MimeTypes.getCharsetFromContentType(_contentType);
    }

    /* ------------------------------------------------------------ */
    @Override
    public Type getMimeType()
    {
        return _contentType==null?null:MimeTypes.CACHE.get(MimeTypes.getContentTypeWithoutCharset(_contentType));
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public HttpField getLastModified()
    {
        long lm = _resource.lastModified();
        return lm>=0?new HttpField(HttpHeader.LAST_MODIFIED,DateGenerator.formatDate(lm)):null;
    }

    /* ------------------------------------------------------------ */
    @Override
    public String getLastModifiedValue()
    {
        long lm = _resource.lastModified();
        return lm>=0?DateGenerator.formatDate(lm):null;
    }

    /* ------------------------------------------------------------ */
    @Override
    public ByteBuffer getDirectBuffer()
    {
        if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
            return null;
        try
        {
            return BufferUtil.toBuffer(_resource,true);
        }
        catch(IOException e)
        {
            throw new RuntimeException(e);
        }
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public HttpField getETag()
    {
        return new HttpField(HttpHeader.ETAG,getETagValue());
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public String getETagValue()
    {
        return _resource.getWeakETag();
    }

    /* ------------------------------------------------------------ */
    @Override
    public ByteBuffer getIndirectBuffer()
    {
        if (_resource.length()<=0 || _maxBuffer>0 && _maxBuffer<_resource.length())
            return null;
        try
        {
            return BufferUtil.toBuffer(_resource,false);
        }
        catch(IOException e)
        {
            throw new RuntimeException(e);
        }
    }

    /* ------------------------------------------------------------ */
    @Override
    public HttpField getContentLength()
    {
        long l=_resource.length();
        return l==-1?null:new HttpField.LongValueHttpField(HttpHeader.CONTENT_LENGTH,l);
    }

    /* ------------------------------------------------------------ */
    @Override
    public long getContentLengthValue()
    {
        return _resource.length();
    }

    /* ------------------------------------------------------------ */
    @Override
    public InputStream getInputStream() throws IOException
    {
        return _resource.getInputStream();
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public ReadableByteChannel getReadableByteChannel() throws IOException
    {
        return _resource.getReadableByteChannel();
    }

    /* ------------------------------------------------------------ */
    @Override
    public Resource getResource()
    {
        return _resource;
    }

    /* ------------------------------------------------------------ */
    @Override
    public void release()
    {
        _resource.close();
    }
    
    /* ------------------------------------------------------------ */
    @Override
    public String toString()
    {
        return String.format("%s@%x{r=%s,ct=%s,c=%b}",this.getClass().getSimpleName(),hashCode(),_resource,_contentType,_precompressedContents!=null);
    }

    /* ------------------------------------------------------------ */
    @Override
    public Map<CompressedContentFormat, HttpContent> getPrecompressedContents()
    {
        return _precompressedContents;
    }

}
