/*
 *  Copyright (c) 2009-2010 jMonkeyEngine
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.jme3.gde.core.j2seproject;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.modules.java.j2seproject.J2SEProject;
import org.netbeans.modules.java.j2seproject.api.J2SEPropertyEvaluator;
import org.netbeans.spi.project.support.ant.AntProjectHelper;
import org.netbeans.spi.project.support.ant.EditableProperties;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.util.Mutex;
import org.openide.util.MutexException;

/**
 * Allows accessing a defined set of properties of a jMonkeyPlatform project
 * @author normenhansen
 */
public class ProjectExtensionProperties {

    private String[] keyList;
    private Project project;
    private EditableProperties properties;
    private String propertyFileName;

    /**
     * Allows accessing a defined set of properties of a jMonkeyPlatform project
     * @param project The project to which the properties are stored
     * @param keyList A list of all property keys this list should use
     */
    public ProjectExtensionProperties(Project project, String[] keyList) {
        this(project, keyList, false);
    }

    /**
     * Allows accessing a defined set of properties of a jMonkeyPlatform project
     * @param project The project to which the properties are stored
     * @param keyList A list of all property keys this list should use
     * @param privateProps If true, saves settings to private (local) properties file
     */
    public ProjectExtensionProperties(Project project, String[] keyList, boolean privateProps) {
        this.project = project;
        this.keyList = keyList;
        properties = new EditableProperties(true);
        if (project instanceof J2SEProject) {
            load();
        }
        if(privateProps){
            propertyFileName = AntProjectHelper.PRIVATE_PROPERTIES_PATH;
        }else{
            propertyFileName = AntProjectHelper.PROJECT_PROPERTIES_PATH;
        }
    }
    
    public EditableProperties getProperties() {
        return properties;
    }

    public String getProperty(String key){
        return properties.getProperty(key);
    }

    public void setProperty(String key, String value){
        if(value==null){
            properties.remove(key);
        }else{
            properties.setProperty(key, value);
        }
    }

    public void load() {
        properties.clear();
        J2SEPropertyEvaluator eval = project.getLookup().lookup(J2SEPropertyEvaluator.class);
        if (eval == null) {
            return;
        }
        for (int i = 0; i < keyList.length; i++) {
            String string = keyList[i];
            String value = eval.evaluator().getProperty(string);
            if (value != null) {
                properties.setProperty(string, value);
            }
        }
    }

    public void store() throws IOException {
        final FileObject projPropsFO = project.getProjectDirectory().getFileObject(propertyFileName);
        if (projPropsFO == null) {
            return;
        }
        final EditableProperties ep = new EditableProperties(true);

        try {
            final InputStream is = projPropsFO.getInputStream();
            ProjectManager.mutex().writeAccess(new Mutex.ExceptionAction<Void>() {

                @Override
                public Void run() throws Exception {
                    try {
                        ep.load(is);
                    } finally {
                        if (is != null) {
                            is.close();
                        }
                    }
                    putProperties(properties, ep);
                    OutputStream os = null;
                    FileLock lock = null;
                    try {
                        lock = projPropsFO.lock();
                        os = projPropsFO.getOutputStream(lock);
                        ep.store(os);
                    } finally {
                        if (lock != null) {
                            lock.releaseLock();
                        }
                        if (os != null) {
                            os.close();
                        }
                    }
                    return null;
                }
            });
        } catch (MutexException mux) {
            throw (IOException) mux.getException();
        }

    }

    private void putProperties(EditableProperties from, EditableProperties to) {
        for (int i = 0; i < keyList.length; i++) {
            String string = keyList[i];
            String value = from.getProperty(string);
            if (value == null || "".equals(value)) {
                to.remove(string);
            } else {
                to.put(string, value);
            }
        }
    }
}
