package org.openstreetmap.josm.plugins.UnitScale;

import org.openstreetmap.josm.data.SystemOfMeasurement;
import org.openstreetmap.josm.spi.preferences.Config;

import java.util.Map;
import java.util.HashMap;
import java.util.Base64;

import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.StringWriter;
import java.io.IOException;

public class UnitScaleUnitManager {
    private static Map<String, SystemSerializer> customUnits = new HashMap<String, SystemSerializer>();

    public static String getFullRepresentation() {
        String out = "";
        for (Map.Entry<String, SystemSerializer> entry : customUnits.entrySet()) {
            out = out.concat(getSystemRepresentation(entry.getValue()));
        }
        return out;
    }

    public static String getSystemRepresentation(SystemSerializer system) {
        StringWriter sw = new StringWriter();
        
        sw.write(String.format("%s\n", system.systemName));
        sw.write(String.format("%s = %f m\n", system.lengthName, system.lengthValue));
        sw.write(String.format("%s = %f m\n", system.longLengthName, system.longLengthValue));
        sw.write(String.format("%s = %f m/s^-1\n", system.speedName, system.speedValue));
        sw.write(String.format("%s = %f m^2\n", system.areaName, system.areaValue));
        
        return sw.toString();
    }
    
    public static void put(SystemOfMeasurement system) {
        customUnits.put(system.getName(), new SystemSerializer(system));
        UnitScaleCommon.allSystemPut(system.getName(), system);
    }
    
    public static void remove(String name) {
        customUnits.remove(name);
        UnitScaleCommon.allSystemRemove(name);
    }
    
    public static void save() {
        Config.getPref().put("UnitScale_customUnits", serialize());
    }
    
    public static void load() {
        for (Map.Entry<String, SystemSerializer> entry : customUnits.entrySet()) {
            UnitScaleCommon.allSystemRemove(entry.getKey());
        }
        
        deserialize(Config.getPref().get("UnitScale_customUnits"));
        
        for (Map.Entry<String, SystemSerializer> entry : customUnits.entrySet()) {
            UnitScaleCommon.allSystemPut(entry.getKey(), entry.getValue().toSoM());
        }
    }
    
    public static String serialize() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            
            oos.writeObject(customUnits);
            
            oos.close();

            return Base64.getEncoder().encodeToString(baos.toByteArray());
        } catch (IOException e) {
            return "";
        }
    }
    
    public static void deserialize(String data) {
        try {
            byte[] b64d = Base64.getDecoder().decode(data);
            ByteArrayInputStream bais = new ByteArrayInputStream(b64d);
            ObjectInputStream ois = new ObjectInputStream(bais);
            
            customUnits = (Map<String, SystemSerializer>) ois.readObject();
            
            ois.close();
        } catch (IOException | ClassNotFoundException e) {
            customUnits = new HashMap<String, SystemSerializer>();
        }
    }
}

