/*
 * Copyright (c) 2009-2010 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jme3.asset.plugins;

import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetKey;
import com.jme3.asset.AssetLocator;
import com.jme3.asset.AssetManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipEntry;

public class HttpZipLocator implements AssetLocator {

    private static final Logger logger = Logger.getLogger(HttpZipLocator.class.getName());

    private URL zipUrl;
    private String rootPath = "";
    private int numEntries;
    private int tableOffset;
    private int tableLength;
    private HashMap<String, ZipEntry2> entries;
    
    private static final ByteBuffer byteBuf = ByteBuffer.allocate(250);
    private static final CharBuffer charBuf = CharBuffer.allocate(250);
    private static final CharsetDecoder utf8Decoder;
    
    static {
        Charset utf8 = Charset.forName("UTF-8");
        utf8Decoder = utf8.newDecoder();
    }

    private static class ZipEntry2 {
        String name;
        int length;
        int offset;
        int compSize;
        long crc;
        boolean deflate;

        @Override
        public String toString(){
            return "ZipEntry[name=" + name +
                         ",  length=" + length +
                         ",  compSize=" + compSize +
                         ",  offset=" + offset + "]";
        }
    }

    private static int get16(byte[] b, int off) {
	return  (b[off++] & 0xff) |
               ((b[off]   & 0xff) << 8);
    }

    private static int get32(byte[] b, int off) {
	return  (b[off++] & 0xff) |
               ((b[off++] & 0xff) << 8) |
               ((b[off++] & 0xff) << 16) |
               ((b[off] & 0xff) << 24);
    }

    private static long getu32(byte[] b, int off) throws IOException{
        return (b[off++]&0xff) |
              ((b[off++]&0xff) << 8) |
              ((b[off++]&0xff) << 16) |
             (((long)(b[off]&0xff)) << 24);
    }

    private static String getUTF8String(byte[] b, int off, int len) throws CharacterCodingException {
        StringBuilder sb = new StringBuilder();
        
        int read = 0;
        while (read < len){
            // Either read n remaining bytes in b or 250 if n is higher.
            int toRead = Math.min(len - read, byteBuf.capacity());
            
            boolean endOfInput = toRead < byteBuf.capacity();
            
            // read 'toRead' bytes into byteBuf
            byteBuf.put(b, off + read, toRead);
            
            // set limit to position and set position to 0
            // so data can be decoded
            byteBuf.flip();
            
            // decode data in byteBuf
            CoderResult result = utf8Decoder.decode(byteBuf, charBuf, endOfInput); 
            
            // if the result is not an underflow its an error
            // that cannot be handled.
            // if the error is an underflow and its the end of input
            // then the decoder expects more bytes but there are no more => error
            if (!result.isUnderflow() || !endOfInput){
                result.throwException();
            }
            
            // flip the char buf to get the string just decoded
            charBuf.flip();
            
            // append the decoded data into the StringBuilder
            sb.append(charBuf.toString());
            
            // clear buffers for next use
            byteBuf.clear();
            charBuf.clear();
            
            read += toRead;
        }
        
        return sb.toString();
    }

    private InputStream readData(int offset, int length) throws IOException{
        HttpURLConnection conn = (HttpURLConnection) zipUrl.openConnection();
        conn.setDoOutput(false);
        conn.setUseCaches(false);
        conn.setInstanceFollowRedirects(false);
        String range = "-";
        if (offset != Integer.MAX_VALUE){
            range = offset + range;
        }
        if (length != Integer.MAX_VALUE){
            if (offset != Integer.MAX_VALUE){
                range = range + (offset + length - 1);
            }else{
                range = range + length;
            }
        }

        conn.setRequestProperty("Range", "bytes=" + range);
        conn.connect();
        if (conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
            return conn.getInputStream();
        }else if (conn.getResponseCode() == HttpURLConnection.HTTP_OK){
            throw new IOException("Your server does not support HTTP feature Content-Range. Please contact your server administrator.");
        }else{
            throw new IOException(conn.getResponseCode() + " " + conn.getResponseMessage());
        }
    }

    private int readTableEntry(byte[] table, int offset) throws IOException{
        if (get32(table, offset) != ZipEntry.CENSIG){
            throw new IOException("Central directory error, expected 'PK12'");
        }

        int nameLen = get16(table, offset + ZipEntry.CENNAM);
        int extraLen = get16(table, offset + ZipEntry.CENEXT);
        int commentLen = get16(table, offset + ZipEntry.CENCOM);
        int newOffset = offset + ZipEntry.CENHDR + nameLen + extraLen + commentLen;

        int flags = get16(table, offset + ZipEntry.CENFLG);
        if ((flags & 1) == 1){
            // ignore this entry, it uses encryption
            return newOffset;
        }
            
        int method = get16(table, offset + ZipEntry.CENHOW);
        if (method != ZipEntry.DEFLATED && method != ZipEntry.STORED){
            // ignore this entry, it uses unknown compression method
            return newOffset;
        }

        String name = getUTF8String(table, offset + ZipEntry.CENHDR, nameLen);
        if (name.charAt(name.length()-1) == '/'){
            // ignore this entry, it is directory node
            // or it has no name (?)
            return newOffset;
        }

        ZipEntry2 entry = new ZipEntry2();
        entry.name     = name;
        entry.deflate  = (method == ZipEntry.DEFLATED);
        entry.crc      = getu32(table, offset + ZipEntry.CENCRC);
        entry.length   = get32(table, offset + ZipEntry.CENLEN);
        entry.compSize = get32(table, offset + ZipEntry.CENSIZ);
        entry.offset   = get32(table, offset + ZipEntry.CENOFF);

        // we want offset directly into file data ..
        // move the offset forward to skip the LOC header
        entry.offset += ZipEntry.LOCHDR + nameLen + extraLen;

        entries.put(entry.name, entry);
        
        return newOffset;
    }

    private void fillByteArray(byte[] array, InputStream source) throws IOException{
        int total = 0;
        int length = array.length;
	while (total < length) {
	    int read = source.read(array, total, length - total);
            if (read < 0)
                throw new IOException("Failed to read entire array");

	    total += read;
	}
    }

    private void readCentralDirectory() throws IOException{
        InputStream in = readData(tableOffset, tableLength);
        byte[] header = new byte[tableLength];

        // Fix for "PK12 bug in town.zip": sometimes
        // not entire byte array will be read with InputStream.read()
        // (especially for big headers)
        fillByteArray(header, in);

//        in.read(header);
        in.close();

        entries = new HashMap<String, ZipEntry2>(numEntries);
        int offset = 0;
        for (int i = 0; i < numEntries; i++){
            offset = readTableEntry(header, offset);
        }
    }

    private void readEndHeader() throws IOException{

//        InputStream in = readData(Integer.MAX_VALUE, ZipEntry.ENDHDR);
//        byte[] header = new byte[ZipEntry.ENDHDR];
//        fillByteArray(header, in);
//        in.close();
//
//        if (get32(header, 0) != ZipEntry.ENDSIG){
//            throw new IOException("End header error, expected 'PK56'");
//        }

        // Fix for "PK56 bug in town.zip":
        // If there's a zip comment inside the end header,
        // PK56 won't appear in the -22 position relative to the end of the
        // file!
        // In that case, we have to search for it.
        // Increase search space to 200 bytes

        InputStream in = readData(Integer.MAX_VALUE, 200);
        byte[] header = new byte[200];
        fillByteArray(header, in);
        in.close();

        int offset = -1;
        for (int i = 200 - 22; i >= 0; i--){
            if (header[i] == (byte) (ZipEntry.ENDSIG & 0xff)
              && get32(header, i) == ZipEntry.ENDSIG){
                // found location
                offset = i;
                break;
            }
        }
        if (offset == -1)
            throw new IOException("Cannot find Zip End Header in file!");

        numEntries  = get16(header, offset + ZipEntry.ENDTOT);
        tableLength = get32(header, offset + ZipEntry.ENDSIZ);
        tableOffset = get32(header, offset + ZipEntry.ENDOFF);
    }

    public void load(URL url) throws IOException {
        if (!url.getProtocol().equals("http"))
            throw new UnsupportedOperationException();

        zipUrl = url;
        readEndHeader();
        readCentralDirectory();
    }

    private InputStream openStream(ZipEntry2 entry) throws IOException{
        InputStream in = readData(entry.offset, entry.compSize);
        if (entry.deflate){
            return new InflaterInputStream(in, new Inflater(true));
        }
        return in;
    }

    public InputStream openStream(String name) throws IOException{
        ZipEntry2 entry = entries.get(name);
        if (entry == null)
            throw new RuntimeException("Entry not found: "+name);

        return openStream(entry);
    }

    public void setRootPath(String path){
        if (!rootPath.equals(path)){
            rootPath = path;
            try {
                load(new URL(path));
            } catch (IOException ex) {
                logger.log(Level.WARNING, "Failed to set root path "+path, ex);
            }
        }
    }

    public AssetInfo locate(AssetManager manager, AssetKey key){
        final ZipEntry2 entry = entries.get(key.getName());
        if (entry == null)
            return null;

        return new AssetInfo(manager, key){
            @Override
            public InputStream openStream() {
                try {
                    return HttpZipLocator.this.openStream(entry);
                } catch (IOException ex) {
                    logger.log(Level.WARNING, "Error retrieving "+entry.name, ex);
                    return null;
                }
            }
        };
    }

}
