package net.sourceforge.ganttproject.calendar;

import java.util.ArrayList;
import java.util.List;

import net.sourceforge.ganttproject.gui.options.model.DefaultEnumerationOption;
import net.sourceforge.ganttproject.gui.options.model.GPOption;
import net.sourceforge.ganttproject.gui.options.model.GPOptionGroup;
import net.sourceforge.ganttproject.parser.ParsingListener;
import net.sourceforge.ganttproject.time.TimeUnit;
import net.sourceforge.ganttproject.time.TimeUnitStack;

/**
 * This class is responsible for loading/saving time unit range settings in a
 * project file
 */
public class TimeUnitRangeOptions extends GPOptionGroup implements ParsingListener {

    public TimeUnitRangeOptions(TimeUnitStack timeUnitStack) {
        super("time-units", createOptions(timeUnitStack));
        lock();
    }

    private static GPOption[] createOptions(TimeUnitStack timeUnitStack) {
        final LoadingSemaphor semaphor = new LoadingSemaphor(timeUnitStack);
        List<String> values = new ArrayList<String>();
        for (TimeUnit timeUnit : timeUnitStack.getTimeUnits()) {
            values.add(timeUnit.getName());
        }
        DefaultEnumerationOption minimalUnit = new DefaultEnumerationOption("minimal-time-unit", values){
            @Override
            public void loadPersistentValue(String value) {
                super.loadPersistentValue(value);
                semaphor.setMinimalUnit(value);
                semaphor.setupUnits();
            }
        };
        minimalUnit.setValue(timeUnitStack.getDefaultTimeUnit().getName());
        DefaultEnumerationOption maximalUnit = new DefaultEnumerationOption("maximal-time-unit", values) {
            @Override
            public void loadPersistentValue(String value) {
                super.loadPersistentValue(value);
                semaphor.setMaximalUnit(value);
            }
            @Override
            public void rollback() {
                super.rollback();
                semaphor.setupUnits();
            }
            public void commit() {
                super.rollback();
                semaphor.setupUnits();
            }
            
        };
        return new GPOption[] {minimalUnit, maximalUnit};
    }

    private static class LoadingSemaphor {
        private final TimeUnitStack myTimeUnitStack;
        private TimeUnit myMinimalUnit;
        private TimeUnit myMaximalUnit;

        LoadingSemaphor(TimeUnitStack timeUnitStack) {
            myTimeUnitStack = timeUnitStack;
        }

        void setupUnits() {
            myTimeUnitStack.setTimeUnitRange(
                    myMinimalUnit==null ? findTimeUnit("day") : myMinimalUnit, myMaximalUnit);
        }

        void setMinimalUnit(String value) {
            myMinimalUnit = findTimeUnit(value);
        }
        
        void setMaximalUnit(String value) {
            myMaximalUnit = findTimeUnit(value);
            if (myMinimalUnit!=null && myMaximalUnit!=null) {
                myTimeUnitStack.setTimeUnitRange(myMinimalUnit, myMaximalUnit);
            }
        }
        
        TimeUnit findTimeUnit(String name) {
            for (TimeUnit timeUnit : myTimeUnitStack.getTimeUnits()) {
                if (timeUnit.getName().equals(name)) {
                    return timeUnit;
                }
            }
            return null;
        }
        
    }

    public void parsingFinished() {
        commit();
    }

    public void parsingStarted() {
    }
}
