/*
 * 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;
    
    public static final long LOCSIG = 0x4034b50, EXTSIG = 0x8074b50,
      CENSIG = 0x2014b50, ENDSIG = 0x6054b50;

    public static final int LOCHDR = 30, EXTHDR = 16, CENHDR = 46, ENDHDR = 22,
      LOCVER = 4, LOCFLG = 6, LOCHOW = 8, LOCTIM = 10, LOCCRC = 14,
      LOCSIZ = 18, LOCLEN = 22, LOCNAM = 26, LOCEXT = 28, EXTCRC = 4,
      EXTSIZ = 8, EXTLEN = 12, CENVEM = 4, CENVER = 6, CENFLG = 8,
      CENHOW = 10, CENTIM = 12, CENCRC = 16, CENSIZ = 20, CENLEN = 24,
      CENNAM = 28, CENEXT = 30, CENCOM = 32, CENDSK = 34, CENATT = 36,
      CENATX = 38, CENOFF = 42, ENDSUB = 8, ENDTOT = 10, ENDSIZ = 12,
      ENDOFF = 16, ENDCOM = 20;

    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) != CENSIG){
            throw new IOException("Central directory error, expected 'PK12'");
        }

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

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

        String name = getUTF8String(table, offset + 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 + CENCRC);
        entry.length   = get32(table, offset + CENLEN);
        entry.compSize = get32(table, offset + CENSIZ);
        entry.offset   = get32(table, offset + CENOFF);

        // we want offset directly into file data ..
        // move the offset forward to skip the LOC header
        entry.offset += 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, ENDHDR);
//        byte[] header = new byte[ENDHDR];
//        fillByteArray(header, in);
//        in.close();
//
//        if (get32(header, 0) != 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) (ENDSIG & 0xff)
              && get32(header, i) == ENDSIG){
                // found location
                offset = i;
                break;
            }
        }
        if (offset == -1)
            throw new IOException("Cannot find Zip End Header in file!");

        numEntries  = get16(header, offset + ENDTOT);
        tableLength = get32(header, offset + ENDSIZ);
        tableOffset = get32(header, offset + 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;
                }
            }
        };
    }

}
