package backtype.storm.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.io.File;

import org.apache.commons.io.FileUtils;

public class VersionedStore {
    private static final String FINISHED_VERSION_SUFFIX = ".version";

    private String _root;
    
    public VersionedStore(String path) throws IOException {
      _root = path;
      mkdirs(_root);
    }

    public String getRoot() {
        return _root;
    }

    public String versionPath(long version) {
        return new File(_root, "" + version).getAbsolutePath();
    }

    public String mostRecentVersionPath() throws IOException {
        Long v = mostRecentVersion();
        if(v==null) return null;
        return versionPath(v);
    }

    public String mostRecentVersionPath(long maxVersion) throws IOException {
        Long v = mostRecentVersion(maxVersion);
        if(v==null) return null;
        return versionPath(v);
    }

    public Long mostRecentVersion() throws IOException {
        List<Long> all = getAllVersions();
        if(all.size()==0) return null;
        return all.get(0);
    }

    public Long mostRecentVersion(long maxVersion) throws IOException {
        List<Long> all = getAllVersions();
        for(Long v: all) {
            if(v <= maxVersion) return v;
        }
        return null;
    }

    public String createVersion() throws IOException {
        Long mostRecent = mostRecentVersion();
        long version = Time.currentTimeMillis();
        if(mostRecent!=null && version <= mostRecent) {
            version = mostRecent + 1;
        }
        return createVersion(version);
    }

    public String createVersion(long version) throws IOException {
        String ret = versionPath(version);
        if(getAllVersions().contains(version))
            throw new RuntimeException("Version already exists or data already exists");
        else
            return ret;
    }

    public void failVersion(String path) throws IOException {
        deleteVersion(validateAndGetVersion(path));
    }

    public void deleteVersion(long version) throws IOException {
        File versionFile = new File(versionPath(version));
        File tokenFile = new File(tokenPath(version));
        
        if(versionFile.exists()) {
            FileUtils.forceDelete(versionFile);
        }
        if(tokenFile.exists()) {
            FileUtils.forceDelete(tokenFile);
        }        
    }

    public void succeedVersion(String path) throws IOException {
        long version = validateAndGetVersion(path);
        // should rewrite this to do a file move
        createNewFile(tokenPath(version));
    }

    public void cleanup() throws IOException {
        cleanup(-1);
    }

    public void cleanup(int versionsToKeep) throws IOException {
        List<Long> versions = getAllVersions();
        if(versionsToKeep >= 0) {
            versions = versions.subList(0, Math.min(versions.size(), versionsToKeep));
        }
        HashSet<Long> keepers = new HashSet<Long>(versions);

        for(String p: listDir(_root)) {
            Long v = parseVersion(p);
            if(v!=null && !keepers.contains(v)) {
                deleteVersion(v);
            }
        }
    }

    /**
     * Sorted from most recent to oldest
     */
    public List<Long> getAllVersions() throws IOException {
        List<Long> ret = new ArrayList<Long>();
        for(String s: listDir(_root)) {
            if(s.endsWith(FINISHED_VERSION_SUFFIX)) {
                ret.add(validateAndGetVersion(s));
            }
        }
        Collections.sort(ret);
        Collections.reverse(ret);
        return ret;
    }

    private String tokenPath(long version) {
        return new File(_root, "" + version + FINISHED_VERSION_SUFFIX).getAbsolutePath();
    }

    private long validateAndGetVersion(String path) {
        Long v = parseVersion(path);
        if(v==null) throw new RuntimeException(path + " is not a valid version");
        return v;
    }

    private Long parseVersion(String path) {
        String name = new File(path).getName();
        if(name.endsWith(FINISHED_VERSION_SUFFIX)) {
            name = name.substring(0, name.length()-FINISHED_VERSION_SUFFIX.length());
        }
        try {
            return Long.parseLong(name);
        } catch(NumberFormatException e) {
            return null;
        }
    }

    private void createNewFile(String path) throws IOException {
        new File(path).createNewFile();
    }

    private void mkdirs(String path) throws IOException {
        new File(path).mkdirs();
    }
    
    private List<String> listDir(String dir) throws IOException {
        List<String> ret = new ArrayList<String>();
        for(File f: new File(dir).listFiles()) {
            ret.add(f.getAbsolutePath());
        }
        return ret;
    }
}
