/**
 * Copyright (c) 2005-2012 by Appcelerator, Inc. All Rights Reserved.
 * Licensed under the terms of the Eclipse Public License (EPL).
 * Please see the license.txt included with this distribution for details.
 * Any modifications to this file must keep this entire header intact.
 */
package org.python.pydev.navigator;

import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.eclipse.core.runtime.Assert;
import org.python.pydev.core.log.Log;
import org.python.pydev.shared_core.string.StringUtils;

/**
 * Helper to get a structure from a zip file
 */
public class ZipStructure {

    private Map<Integer, TreeSet<String>> levelToContents = new HashMap<Integer, TreeSet<String>>();
    public final File file;

    /*package*/ ZipStructure() { //just for testing
        this.file = null;
    }

    /**
     * @param file the file that's treated as a zip
     * @param zipFile the zip wrapping of the passed file
     */
    public ZipStructure(File file, ZipFile zipFile) {
        this.file = file;
        Enumeration<? extends ZipEntry> entries = zipFile.entries();

        while (entries.hasMoreElements()) {
            String name;
            try {
                ZipEntry element = entries.nextElement();
                name = element.getName();
            } catch (Exception e) {
                Log.log(e);
                continue;
            }
            final List<String> split = StringUtils.split(name, '/');
            int size = split.size();
            int level = size - 1;
            TreeSet<String> treeSet = levelToContents.get(level);
            if (treeSet == null) {
                treeSet = new TreeSet<String>();
                levelToContents.put(level, treeSet);
            }
            treeSet.add(name);

            //Add for parent entries (it's possible to have an entry folder/entry.py and the folder/
            //wouldn't appear in our structure).
            if (size == 1) {
                continue;
            }
            String[] array = split.toArray(new String[size]);
            for (int i = 0; i < size - 1; i++) {
                name = StringUtils.join("/", array, 0, i + 1) + "/";
                level = i;
                treeSet = levelToContents.get(level);
                if (treeSet == null) {
                    treeSet = new TreeSet<String>();
                    levelToContents.put(level, treeSet);
                }
                treeSet.add(name);
            }
        }
    }

    /*package*/Map<Integer, TreeSet<String>> getLevelToContents() {
        return levelToContents;
    }

    /**
     * In this method we'll get the contents within the zip file for the passed directory
     *
     * @param string: Must be a directory within the zip file or an empty string to get the root contents
     */
    public List<String> contents(String name) {
        ArrayList<String> ret = new ArrayList<String>();

        int level;
        int length = name.length();
        if (length == 0) {
            level = 0;
        } else {
            Assert.isTrue(StringUtils.endsWith(name, '/')); //must be a directory
            level = StringUtils.count(name, '/');
        }

        TreeSet<String> treeSet = levelToContents.get(level);
        if (treeSet != null) {
            if (length == 0) {
                ret.addAll(treeSet);
            } else {
                for (String s : treeSet.tailSet(name)) {
                    if (s.startsWith(name)) {
                        ret.add(s);
                    }
                }
            }
        }

        return ret;
    }

}
