/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.modules.maven;

import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelBuildingException;
import org.netbeans.api.project.Project;
import org.netbeans.modules.maven.api.Constants;
import org.netbeans.modules.maven.spi.PackagingProvider;
import org.netbeans.spi.project.AuxiliaryConfiguration;
import org.netbeans.spi.project.AuxiliaryProperties;
import org.netbeans.spi.project.LookupMerger;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
import org.openide.util.lookup.ServiceProvider;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Comment;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * implementation of AuxiliaryProperties.
 * @author mkleint
 */
public class MavenProjectPropsImpl {

    private static final String NAMESPACE = "http://www.netbeans.org/ns/maven-properties-data/1"; //NOI18N
    private static final String ROOT = "properties"; //NOI18N

    private static final Logger LOG = Logger.getLogger(MavenProjectPropsImpl.class.getName());

    private final AuxiliaryConfiguration aux;
    private boolean sharedChanged;
    private final NbMavenProjectImpl nbprji;
    private Mutex mutex;

    MavenProjectPropsImpl(AuxiliaryConfiguration aux, NbMavenProjectImpl pr) {
        this.aux = aux;
        nbprji = pr;
    }

    private AuxiliaryConfiguration getAuxConf() {
        return aux;
    }

    public String get(String key, boolean shared) {
        return get(key, shared, true);
    }

    public String get(String key, boolean shared, boolean usePom) {
        return getMutex().readAccess((Mutex.Action<String>) () -> {
            TreeMap<String, String> props = readProperties(getAuxConf(), shared);
            //TODO optimize
            String ret =  props.get(key);
            if (ret != null) {
                return ret;
            }
            if (shared && usePom) {
                if(Constants.HINT_PACKAGING.equals(key) && !nbprji.isMavenProjectLoaded()) {
                    // issue #262646 
                    // due to unfortunate ProjectManager.findPorjetc calls in awt, 
                    // speed is essential during project init, so lets try to avoid
                    // maven project loading if we can get the info faster from raw model.
                    Model model;  
                    try {
                        model = nbprji.getProjectWatcher().getRawModel();
                    } catch (ModelBuildingException ex) {
                        // whatever happend, we can't use the model, 
                        // lets try to follow up with loading the maven project
                        model = null;
                        LOG.log(Level.FINE, null, ex);
                    }
                    String val = model != null ? model.getPackaging() : null;
                    // In the unfortunate case that the project packaging contains value reference, it's probably
                    // better not to provide anything: packaging affects Project Lookup and things may get screwed up.
                    if (val != null && !val.contains("${")) {
                        return val;
                    }   
                }
                String val = nbprji.getOriginalMavenProject().getProperties().getProperty(key);
                if (val != null) {
                    return val;
                }
            }
            return null;
        });                       
    }

    public void put(String key, String value, boolean shared) {
        getMutex().writeAccess((Mutex.Action<Void>) () -> {
            if (shared) {
                //TODO put props to project.. shall we actually do it here?
            }
            writeAuxiliaryData(getAuxConf(), key, value, shared);
            return null;
        });
    }

    public Iterable<String> listKeys(boolean shared) {
        return getMutex().readAccess((Mutex.Action<Iterable<String>>) () -> {
            TreeMap<String, String> props = readProperties(getAuxConf(), shared);
            if (shared) {
                Properties mvnprops =  nbprji.getOriginalMavenProject().getProperties();
                for (Object prop: mvnprops.keySet()) {
                    props.put((String)prop, "any"); //NOI18N
                }
            }
            return props.keySet();
        });    
    }

    private void writeAuxiliaryData(AuxiliaryConfiguration conf, String property, String value, boolean shared) {
        Element el = getOrCreateRootElement(conf, shared);
        Element enEl;
        NodeList list = el.getElementsByTagNameNS(NAMESPACE, property);
        if (list.getLength() > 0) {
            enEl = (Element)list.item(0);
        } else {
            try {
                enEl = el.getOwnerDocument().createElementNS(NAMESPACE, property);
            } catch (DOMException x) {
                LOG.log(Level.WARNING, "#200901: {0} from {1}", new Object[] {x.getMessage(), property});
                return;
            }
            el.appendChild(enEl);
        }
        if (value != null) {
            enEl.setTextContent(value);
        } else {
            el.removeChild(enEl);
        }
        if (el.getElementsByTagNameNS(NAMESPACE, "*").getLength() > 0) {
            conf.putConfigurationFragment(el, shared);
        } else {
            conf.removeConfigurationFragment(ROOT, NAMESPACE, shared);
        }
    }

    public static void writeAuxiliaryData(AuxiliaryConfiguration conf, TreeMap<String, String> props, boolean shared) {
        Element el = getOrCreateRootElement(conf, shared);
        Element enEl;
        for (String key : props.keySet()) {
            NodeList list = el.getElementsByTagNameNS(NAMESPACE, key);
            if (list.getLength() > 0) {
                enEl = (Element)list.item(0);
            } else {
                try {
                    enEl = el.getOwnerDocument().createElementNS(NAMESPACE, key);
                } catch (DOMException x) {
                    LOG.log(Level.WARNING, "#200901: {0} from {1}", new Object[] {x.getMessage(), key});
                    continue;
                }
                el.appendChild(enEl);
            }
            String value = props.get(key);
            if (value != null) {
                enEl.setTextContent(value);
            } else {
                el.removeChild(enEl);
            }
        }
        if (el.getElementsByTagNameNS(NAMESPACE, "*").getLength() > 0) {
            conf.putConfigurationFragment(el, shared);
        } else {
            conf.removeConfigurationFragment(ROOT, NAMESPACE, shared);
        }
    }

    private static Element getOrCreateRootElement(AuxiliaryConfiguration conf, boolean shared) {
        Element el = conf.getConfigurationFragment(ROOT, NAMESPACE, shared);
        if (el == null) {
            el = XMLUtil.createDocument(ROOT, NAMESPACE, null, null).getDocumentElement();
            if (shared) {
                Comment comment = el.getOwnerDocument().createComment("\nProperties that influence various parts of the IDE, especially code formatting and the like. \n" + //NOI18N
                        "You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.\n" + //NOI18N
                        "That way multiple projects can share the same settings (useful for formatting rules for example).\n" + //NOI18N
                        "Any value defined here will override the pom.xml file value but is only applicable to the current project.\n"); //NOI18N
                el.appendChild(comment);
            }
        }
        return el;
    }


    private TreeMap<String, String> readProperties(AuxiliaryConfiguration aux, boolean shared) {
        return getMutex().readAccess((Mutex.Action<TreeMap<String, String>>) () -> {
            TreeMap<String, String> props = new TreeMap<>();
            Element el = aux.getConfigurationFragment(ROOT, NAMESPACE, shared);
            if (el != null) {
                NodeList list = el.getChildNodes();
                if (list.getLength() > 0) {
                    for (int i = 0; i < list.getLength(); i++) {
                        Node nd = list.item(i);
                        if (nd instanceof Element) {
                            Element enEl = (Element)nd;
                            props.put(enEl.getNodeName(), enEl.getTextContent());
                        }
                    }
                }
            }
            return props;
        });    
    }

    public TreeMap<String, String> getRawProperties(boolean shared) {
        return readProperties(getAuxConf(), shared);
    }

    private synchronized Mutex getMutex() {
        if(mutex == null) {
            mutex = new Mutex();
        }
        return mutex;
    }

    static class Merger implements LookupMerger<AuxiliaryProperties> {
        private final MavenProjectPropsImpl primary;

        Merger(MavenProjectPropsImpl primary) {
            this.primary = primary;
        }

        public @Override Class<AuxiliaryProperties> getMergeableClass() {
            return AuxiliaryProperties.class;
        }

        public @Override AuxiliaryProperties merge(Lookup lookup) {
            return new MergedAuxProperties(lookup, primary);
        }

    }

    private static class MergedAuxProperties implements AuxiliaryProperties {
        Lookup.Result<AuxiliaryProperties> props;
        private final MavenProjectPropsImpl primary;
        private MergedAuxProperties(Lookup lookup, MavenProjectPropsImpl primary) {
             props = lookup.lookupResult(AuxiliaryProperties.class);
             this.primary = primary;
        }


        public @Override String get(String key, boolean shared) {
            String toRet = primary.get(key, shared);
            if (toRet == null) {
                for (AuxiliaryProperties prop : props.allInstances()) {
                    toRet = prop.get(key, shared);
                    if (toRet != null) {
                        break;
                    }
                }
            }
            return toRet;
        }

        public @Override void put(String key, String value, boolean shared) {
            primary.put(key, value, shared);
        }

        public @Override Iterable<String> listKeys(boolean shared) {
            Set<String> toRet = new TreeSet<String>();
            Iterator<String> s = primary.listKeys(shared).iterator();
            while (s.hasNext()) {
                toRet.add(s.next());
            }
            for (AuxiliaryProperties aux : props.allInstances()) {
                s = aux.listKeys(shared).iterator();
                while (s.hasNext()) {
                    toRet.add(s.next());
                }
            }
            return toRet;
        }

    }

    @ServiceProvider(service=PackagingProvider.class, position=1000)
    public static class PackagingProviderImpl implements PackagingProvider {
        @Override public String packaging(Project project) {
            return project.getLookup().lookup(MavenProjectPropsImpl.class).get(Constants.HINT_PACKAGING, true);
        }
    }

}
