package com.izforge.izpack.panels;

import com.izforge.izpack.installer.InstallData;
import com.izforge.izpack.installer.InstallerFrame;
import net.n3.nanoxml.*;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * @author dmitry.antonov
 */
public class CustomPathPanel extends PathInputPanel {

    public static final String SPEC_FILE_NAME = "customPathInput.xml";
    public static final String PANEL_NODE = "panel";
    public static final String ID_NODE = "order";
    public static final String LABEL_NODE = "label";
    public static final String VARIABLE_NAME_NODE = "variable";
    public static final String INIT_PATH_NODE = "init_path"; 
    public static final String RES_NOT_FOUND_MESSAGE = "Required resources were not found!";
    public static final String CONDITION_ELEMENT = "condition";
    public static final String CONDITION_VAR = "varname";
    public static final String CONDITION_VALUE = "value";
    public static final String CHECKFILES = "files";

    private static int instanceCount = 0;

    private String variableName;
    private String initPath;
    private final int id;
    private final List conditions = new ArrayList(); 

    private class Condition {
        public final String files;
        public final String label;
        public final String conditionVariable;
        public final String conditionValue;
        public Condition(XMLElement element) {
            files = element.getAttribute(CHECKFILES);
            label = element.getAttribute(LABEL_NODE);
            conditionVariable = element.getAttribute(CONDITION_VAR);
            conditionValue = element.getAttribute(CONDITION_VALUE);
        }

        public boolean isAppropriate() {
            return conditionValue.equals(idata.getVariable(conditionVariable));
        }
        
        public void apply() {
            setLabel(label);
            setRequiredFiles(files);
        }
    }

    public CustomPathPanel(InstallerFrame parent, InstallData idata) {
        super(parent, idata);
        id = instanceCount++;
        readSpec(parent);
    }

    private void setRequiredFiles(String files) {
        if (files != null && files.length() > 0) {
            existFiles = files.split(",");
            setMustExist(true);
        }
        else {
            setMustExist(false);
        }
    }

    private void setLabel(String labelText) {
        if (labelText != null && labelText.length() > 0) {
            Component[] components = getComponents();
            for (int i = 0; i < components.length; i++) {
                if (components[i] instanceof JLabel) {
                    ((JLabel) components[i]).setText(labelText);
                    break;
                }
            }
        }
    }

    private void processConditions(List conditions) {
        for (Iterator iterator = conditions.iterator(); iterator.hasNext();) {
            this.conditions.add(new Condition((XMLElement) iterator.next()));
        }
    }

    public void readSpec(InstallerFrame parentFrame) {
        try {
            InputStream is = parentFrame.getResource(SPEC_FILE_NAME);
            // initialize the parser
            StdXMLParser parser = new StdXMLParser();
            parser.setBuilder(new StdXMLBuilder());
            parser.setValidator(new NonValidator());
            parser.setReader(new StdXMLReader(is));
            // get the data
            XMLElement data = (XMLElement) parser.parse();
            List childs = data.getChildrenNamed(PANEL_NODE);
            for (Iterator it = childs.iterator(); it.hasNext();) {
                XMLElement e = (XMLElement)it.next();
                if (Integer.toString(id).equals(e.getAttribute(ID_NODE))) {
                    variableName = e.getAttribute(VARIABLE_NAME_NODE);
                    initPath = e.getAttribute(INIT_PATH_NODE);
                    List conditions = e.getChildrenNamed(CONDITION_ELEMENT);
                    if (!conditions.isEmpty()) {
                        processConditions(conditions);
                    }
                    else {
                        setLabel(e.getAttribute(LABEL_NODE));
                        setRequiredFiles(e.getAttribute(CHECKFILES));
                    }
                    return;
                }
            }
            throw new RuntimeException(RES_NOT_FOUND_MESSAGE);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

    /** Called when the panel becomes active. */
    public void panelActivate()
    {
        super.panelActivate();
        System.out.println("CustomPathPanel activated");
        System.out.println("Conditions count = " + conditions.size());
        for (Iterator iterator = conditions.iterator(); iterator.hasNext();) {
            Condition condition = (Condition) iterator.next();
            if (condition.isAppropriate()) {
                condition.apply();
            }
        }
        String chosenPath = idata.getVariable("APPLICATIONS_DEFAULT_ROOT");
        if (initPath != null) {
            chosenPath = chosenPath + File.separator + initPath;
        }
        // The variable will be exist if we enter this panel
        // second time. We would maintain the previos
        // selected path.
        // Set the path for method pathIsValid ...
        pathSelectionPanel.setPath(chosenPath);
        // Set the default to the path selection panel.
        pathSelectionPanel.setPath(chosenPath);
        if (chosenPath.length() > 0)
        {
            idata.setVariable(variableName, chosenPath);
        }
    }


    public boolean isValidated() {
        boolean result = super.isValidated();
        if (result) {
            idata.setVariable(variableName, pathSelectionPanel.getPath());
        }
        return result;
    }
}
