package net.sourceforge.ganttproject.gui.taskproperties;

import java.util.Arrays;

import javax.swing.JComponent;

import net.sourceforge.ganttproject.IGanttProject;
import net.sourceforge.ganttproject.gui.UIFacade;
import net.sourceforge.ganttproject.gui.options.OptionsPageBuilder;
import net.sourceforge.ganttproject.gui.options.model.BooleanOption;
import net.sourceforge.ganttproject.gui.options.model.ChangeValueEvent;
import net.sourceforge.ganttproject.gui.options.model.ChangeValueListener;
import net.sourceforge.ganttproject.gui.options.model.DefaultBooleanOption;
import net.sourceforge.ganttproject.gui.options.model.DefaultEnumerationOption;
import net.sourceforge.ganttproject.gui.options.model.DefaultStringOption;
import net.sourceforge.ganttproject.gui.options.model.EnumerationOption;
import net.sourceforge.ganttproject.gui.options.model.GPOption;
import net.sourceforge.ganttproject.gui.options.model.GPOptionGroup;
import net.sourceforge.ganttproject.gui.options.model.StringOption;
import net.sourceforge.ganttproject.gui.options.model.ValidationException;
import net.sourceforge.ganttproject.language.GanttLanguage;
import net.sourceforge.ganttproject.task.Task;
import net.sourceforge.ganttproject.task.TaskMutator;
import net.sourceforge.ganttproject.task.TaskTimeInterval;

public class MainPage implements IPropertySheetComponent {
    private TaskScheduleFields myTaskScheduleFields;
    private GPOptionGroup myMainPropertiesGroup;
	private Task myTask;
	private IGanttProject myProject;
    private TaskMutator myTaskMutator;
	private OptionsPageBuilder myBuilder = new OptionsPageBuilder();
	private boolean isCollapsed;
	private boolean isHidden;
	private TaskTimeInterval myTimeInterval;
    
	public String getPageName() {
		return GanttLanguage.getInstance().getText("taskProperties.tab.general.label");
	}

	public void init(Task task, TaskMutator taskMutator, IGanttProject project, UIFacade uifacade) {
		myTask = task;
		myTaskMutator = taskMutator;
		myProject = project;
        myMainPropertiesGroup = createMainProperties();
        myMainPropertiesGroup.setTitled(false);
        myMainPropertiesGroup.lock();
	}

	public void onCommit() {
        myMainPropertiesGroup.commit();
        myTaskMutator.commit();
	}

	public void onRollback() {
		myTaskMutator.rollback();
        myMainPropertiesGroup.rollback();
	}

	public Object getAdapter(Class adapter) {
		if (JComponent.class.equals(adapter)) {
			return myBuilder.createGroupComponent(myMainPropertiesGroup);
		}
		return null;
	}

	
    private GPOptionGroup createMainProperties() {
        myTaskScheduleFields = new TaskScheduleFields() {
            @Override
            protected void apply() {
                if (myMainPropertiesGroup.isChanged()) {
                    applyValues();
                }
                else {
                    resetMutator();
                }
            }
            @Override
            protected TaskTimeInterval getTimeInterval() {
                return myTimeInterval;
            }
            @Override
            protected Task getTask() {
                return myTask;
            }
			@Override
			protected IGanttProject getProject() {
				return myProject;
			}
        };        
        final StringOption nameField = new DefaultStringOption("taskProperties.main.name") {
            @Override
            public void commit() {
                super.commit();
                myTaskMutator.setName(getValue());
            }
        };
        nameField.setValue(myTask.getName());
        final BooleanOption milestone = new DefaultBooleanOption("taskProperties.main.milestone", myTask.isMilestone()) {
            public void commit() {
                super.commit();
                myTaskMutator.setMilestone(isChecked());
            }
            
        };
        milestone.addChangeValueListener(new ChangeValueListener() {
            {
                onMilestoneToggle(myTask.isMilestone());
            }
            public void changeValue(ChangeValueEvent event) {
                onMilestoneToggle((Boolean)event.getNewValue());
            }

            private void onMilestoneToggle(Boolean isMilestone) {
                myTaskScheduleFields.myDurationOption.setWritable(!isMilestone.booleanValue());
                myTaskScheduleFields.myEndDateOption.setWritable(!isMilestone.booleanValue());
            }
        });
        myTaskScheduleFields.myDurationOption.setWritable(false);
        resetMutator();
        final StringOption completion = new  DefaultStringOption("taskProperties.main.completion") {
			@Override
			public void setValue(String value) {
				try {
					int completion = Integer.parseInt(value);
					if (completion<0 || completion>100) {
						throw new ValidationException();
					}
				}
				catch(NumberFormatException e) {
					throw new ValidationException("", e);
				}
				super.setValue(value);
			}

			@Override
			public void commit() {
				super.commit();
                if (getValue()!=null) {
                    myTaskMutator.setCompletionPercentage(Integer.parseInt(getValue()));
                }
			}        	
        };
        completion.setValue(String.valueOf(myTask.getCompletionPercentage()));
        final EnumerationOption priority = new DefaultEnumerationOption("taskProperties.main.priority", new String[] {
                "high", "medium", "low"
        }) {
			@Override
			public void commit() {
				super.commit();
				if (getValue()!=null) {
					for (int i = 0; i < Priorities.values().length; i++) {
						if (Priorities.values()[i].toString().equals(getValue())) {
							myTaskMutator.setPriority(i);
						}
					}
				}
			}
        	
        };
        priority.setValue(Priorities.values()[myTask.getPriority()].toString());
        return new GPOptionGroup("taskProperties.main", new GPOption[]{
                nameField, milestone, myTaskScheduleFields.myStartDateOption, myTaskScheduleFields.myEndDateOption, myTaskScheduleFields.myDurationOption, completion, priority 
        });
        
    }
    
    static enum Priorities {
    	high, medium, low
    }
    /**
     * Added LaboPM
     * Creates cost properties option group
     * @return
     */
    /*
	*/
    private void applyValues() {
        myMainPropertiesGroup.commit();
        myTaskMutator.commit();
        myTimeInterval = myTaskScheduleFields.myDurationOption.isWritable() ? 
        		myTaskMutator.createRegularTimeInterval() : 
        	    myTaskMutator.createFixedDurationTimeInterval();
        myMainPropertiesGroup.lock();
    }
    private void resetMutator() {
        myTaskMutator.rollback();
        myTimeInterval = myTaskScheduleFields.myDurationOption.isWritable() ? 
        		myTaskMutator.createRegularTimeInterval() : 
        	    myTaskMutator.createFixedDurationTimeInterval();
    }

	public String getTitle() {
		return myBuilder.getI18N().getOptionGroupLabel(myMainPropertiesGroup);
	}

	public boolean isCollapsed() {
		return isCollapsed;
	}

	public void setCollapsed(boolean collapsed) {
		isCollapsed = collapsed;
	}

	public boolean isHidden() {
		return isHidden;
	}

	public void setHidden(boolean hidden) {
		isHidden = hidden;
	}
    
}
