package usda.weru.weps.location;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import java.io.IOException;
import javax.measure.Measurable;
import javax.measure.quantity.Length;
import org.apache.log4j.Logger;
import org.jscience.geography.coordinates.LatLong;
import usda.weru.util.CligenData;
import usda.weru.util.CligenDataFormat;
import usda.weru.util.RelativeFileContext;
import usda.weru.util.Util;

/**
 *
 * @author Joseph Levin <joelevin@weru.ksu.edu>
 */
public class FileStation implements Station {

    private static final Logger LOGGER = Logger.getLogger(FileStation.class);
    private final TFile c_file;
    private Measurable<Length> c_elevation;

    /**
     *
     * @param file
     */
    public FileStation(TFile file) {
        c_file = file;
    }

    @Override
    public String getDisplayName() {
        return c_file.getName();
    }

    @Override
    public LatLong getLatLong() {
        return null;
    }

    /**
     *
     * @return
     */
    @Override
    public Measurable<Length> getElevation() {
        synchronized (this) {
            if (c_elevation == null) {
                //are we cligen or windgen?
                if (c_file != null && c_file.getName().toLowerCase().endsWith(".cli")) {
                    //cligen
                    CligenData data = new CligenData();
                    CligenDataFormat format = new CligenDataFormat();
                    try {
                        format.read(data, new TFileInputStream(c_file));
                        c_elevation = data.getElevation();
                    } catch (IOException ioe) {
                        LOGGER.error("Unable to read cligen data for file: " + c_file.getAbsolutePath(), ioe);
                    }
                } else if (c_file != null && c_file.getName().toLowerCase().endsWith(".win")) {
                    //windgen
                    //TODO: add windgen support in the future
                } else {
                    //TODO: try and resolve the file type for a non standard extenstion
                }
            }
        }
        return c_elevation;
    }

    /**
     *
     * @return
     */
    public TFile getFile() {
        return c_file;
    }

    /**
     *
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final FileStation other = (FileStation) obj;
        if (this.c_file != other.c_file && (this.c_file == null || !this.c_file.equals(other.c_file))) {
            return false;
        }
        return true;
    }

    /**
     *
     * @return
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + (this.c_file != null ? this.c_file.hashCode() : 0);
        return hash;
    }

    /**
     *
     * @param station
     * @return
     */
    public static String serialize(FileStation station) {
        if (station == null) {
            return null;
        }

        TFile relative = RelativeFileContext.getFile();
        if (relative != null) {
            //attempt to resolve the file as relative
            TFile file = Util.resolveFileAsRelativeChildOrAbsolute(relative, station.getFile());
            return "2|" + file.getPath();
        } else {
            LOGGER.error("FileStation serialization should occur within a RelativeFileContext.");
            //version 1:  "1|path/to/file/here.win"
            //old version, assume absoulte path
            return "1|" + station.getFile().getPath();

        }
    }

    /**
     *
     * @param value
     * @return
     */
    public static FileStation deserialize(final String value) {
        if (value == null || value.trim().length() == 0) {
            return null;
        }

        String[] parts = value.split("\\|");

        //first part is the version number to allow for future changes
        int version = 0;
        try {
            version = Integer.valueOf(parts[0].trim());
        } catch (NumberFormatException e) {
            //must not of had a version number
            LOGGER.error("Unable to deserialize the FileStation : " + value, e);
            return null;
        }
        if (parts.length != 2) {
            LOGGER.warn("Unexpected number of serialization parts. " + String.valueOf(parts.length));
            return null;
        }
        switch (version) {
            case 1:
            case 2:
                //supports relative paths
                TFile relative = RelativeFileContext.getFile();

                if (relative != null) {
                    //attempt to resolve the file as relative
                    TFile temp = new TFile(parts[1].trim());
                    if (temp.isAbsolute()) {
                        return new FileStation(temp);
                    } else {
                        return new FileStation(new TFile(relative, temp.getName()));
                    }

                } else {
                    LOGGER.error("FileStation deserialization should occur within a RelativeFileContext.");
                    TFile old = new TFile(parts[1].trim());
                    return new FileStation(old);
                    //throw new IllegalStateException();
                }

            default:
                LOGGER.warn("Unsupported FileStation serialization version: " + String.valueOf(version));
                return null;
        }

    }
}
