package org.jetbrains.idea.project.filetemplate;

import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.util.text.UniqueNameGenerator;
import org.jdom.Attribute;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;

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

/**
 * Created by IntelliJ IDEA.
 * Author: Vladimir Kravets
 * E-Mail: vova.kravets@gmail.com
 * Date: 2/14/14
 * Time: 5:35 PM
 */
@State(name = "ProjectTemplateVariables",
        storages = {
                @Storage(file = StoragePathMacros.PROJECT_FILE),
                @Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/template/", scheme = StorageScheme.DIRECTORY_BASED,
                         stateSplitter = PerProjectTemplateManager.ProjectTemplateStateSplitter.class)
        }
      )
public class PerProjectTemplateManager extends AbstractProjectComponent implements PersistentStateComponent<Element> {

    private Properties projectVariables;

    protected PerProjectTemplateManager(Project project) {
        super(project);
        projectVariables = new Properties();
    }

    private static final String VARIABLE_TAG = "variable";
    private static final String VARIABLE_NAME_ATTR = "name";
    private static final String TEMPLATE_VARIABLES = "templateVariables";

    @Nullable
    @Override
    public Element getState() {
        Element root = new Element(TEMPLATE_VARIABLES);
        for (String name : projectVariables.stringPropertyNames()) {
            Element variable = new Element(VARIABLE_TAG);
            variable.setAttribute(VARIABLE_NAME_ATTR, name);
            variable.addContent(projectVariables.getProperty(name));
            root.addContent(variable);
        }
        return root;
    }

    @Override
    public void loadState(Element element) {
        projectVariables.clear();
        List<Element> elements = JDOMUtil.getChildren(element, TEMPLATE_VARIABLES);
        if (elements.size() > 0) {
            elements = JDOMUtil.getChildren(elements.get(0), VARIABLE_TAG);
            for (Element variable : elements) {
                Attribute attribute = variable.getAttribute(VARIABLE_NAME_ATTR);
                if (attribute != null && attribute.getValue() != null) {
                    projectVariables.put(attribute.getValue(), variable.getValue());
                }
            }
        }
    }

    public static class ProjectTemplateStateSplitter implements StateSplitter{

        public ProjectTemplateStateSplitter() {
        }

        @Override
        public List<Pair<Element, String>> splitState(Element e) {
            final UniqueNameGenerator generator = new UniqueNameGenerator();
            final List<Pair<Element, String>> result = new ArrayList<Pair<Element, String>>();
            result.add(new Pair<Element, String>(e, generator.generateUniqueName("template_variable_settings") + ".xml"));
            return result;
        }

        @Override
        public void mergeStatesInto(Element target, Element[] elements) {
            for (Element element : elements) {
                if (element.getName().equals(TEMPLATE_VARIABLES)) {
                    element.detach();
                    Element child = target.getChild(TEMPLATE_VARIABLES);
                    if (child == null) {
                        child = new Element(TEMPLATE_VARIABLES);
                        target.addContent(child);
                    }
                    Element[] variables = JDOMUtil.getElements(element);
                    for (Element variable : variables) {
                        variable.detach();
                        child.addContent(variable);
                    }
                }
                else {
                    final Element[] states = JDOMUtil.getElements(element);
                    for (Element state : states) {
                        state.detach();
                        target.addContent(state);
                    }
                    for (Object attr : element.getAttributes()) {
                        target.setAttribute(((Attribute)attr).clone());
                    }
                }
            }
        }
    }

    public static PerProjectTemplateManager getInstance(Project project) {
        return project.getComponent(PerProjectTemplateManager.class);
    }


    public Properties getProjectVariables() {
        return projectVariables;
    }
}

@@ -130,16 +130,73 @@
 roject;%0A
+import com.intellij.openapi.project.impl.DefaultProject;%0A
 import c
@@ -2161,32 +2161,409 @@
 0) %7B%0A           
+ updateVariablesFromElement(elements.get(0));%0A        %7D else %7B%0A            // Workaround for DefaultProject storage behavior%0A            // it's save information without root element, in our case without TEMPLATE_VARIABLES tag%0A            updateVariablesFromElement(element);%0A        %7D%0A    %7D%0A%0A    private void updateVariablesFromElement(Element element) %7B%0A        List%3CElement%3E
  elements = JDOM
@@ -2586,24 +2586,16 @@
 (element
-s.get(0)
 , VARIAB
@@ -2595,36 +2595,32 @@
  VARIABLE_TAG);%0A
-    
         for (Ele
@@ -2639,36 +2639,32 @@
 e : elements) %7B%0A
-    
             Attr
@@ -2732,28 +2732,24 @@
             
-    
 if (attribut
@@ -2785,36 +2785,32 @@
 ue() != null) %7B%0A
-    
                 
@@ -2874,34 +2874,16 @@
 lue());%0A
-                %7D%0A
         

Fix issue #1 with loading Default Project settings again