/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed 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 com.android.sdklib.internal.project;

import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Class to load and save project properties for both ADT and Ant-based build.
 *
 */
public final class ProjectProperties {
    /** The property name for the project target */
    public final static String PROPERTY_TARGET = "target";

    public final static String PROPERTY_SDK = "sdk.dir";
    // LEGACY - compatibility with 1.6 and before
    public final static String PROPERTY_SDK_LEGACY = "sdk-location";

    public final static String PROPERTY_APP_PACKAGE = "application.package";
    // LEGACY - compatibility with 1.6 and before
    public final static String PROPERTY_APP_PACKAGE_LEGACY = "application-package";

    public final static String PROPERTY_SPLIT_BY_DENSITY = "split.density";

    public final static String PROPERTY_TESTED_PROJECT = "tested.project.dir";

    public static enum PropertyType {
        BUILD("build.properties", BUILD_HEADER),
        DEFAULT("default.properties", DEFAULT_HEADER),
        LOCAL("local.properties", LOCAL_HEADER);

        private final String mFilename;
        private final String mHeader;

        PropertyType(String filename, String header) {
            mFilename = filename;
            mHeader = header;
        }

        public String getFilename() {
            return mFilename;
        }
    }

    private final static String LOCAL_HEADER =
//           1-------10--------20--------30--------40--------50--------60--------70--------80
            "# This file is automatically generated by Android Tools.\n" +
            "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
            "# \n" +
            "# This file must *NOT* be checked in Version Control Systems,\n" +
            "# as it contains information specific to your local configuration.\n" +
            "\n";

    private final static String DEFAULT_HEADER =
//          1-------10--------20--------30--------40--------50--------60--------70--------80
           "# This file is automatically generated by Android Tools.\n" +
           "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
           "# \n" +
           "# This file must be checked in Version Control Systems.\n" +
           "# \n" +
           "# To customize properties used by the Ant build system use,\n" +
           "# \"build.properties\", and override values to adapt the script to your\n" +
           "# project structure.\n" +
           "\n";

    private final static String BUILD_HEADER =
//          1-------10--------20--------30--------40--------50--------60--------70--------80
           "# This file is used to override default values used by the Ant build system.\n" +
           "# \n" +
           "# This file must be checked in Version Control Systems, as it is\n" +
           "# integral to the build system of your project.\n" +
           "\n" +
           "# This file is only used by the Ant script.\n" +
           "\n" +
           "# You can use this to override default values such as\n" +
           "#  'source.dir' for the location of your java source folder and\n" +
           "#  'out.dir' for the location of your output folder.\n" +
           "\n" +
           "# You can also use it define how the release builds are signed by declaring\n" +
           "# the following properties:\n" +
           "#  'key.store' for the location of your keystore and\n" +
           "#  'key.alias' for the name of the key to use.\n" +
           "# The password will be asked during the build when you use the 'release' target.\n" +
           "\n";

    private final static Map<String, String> COMMENT_MAP = new HashMap<String, String>();
    static {
//               1-------10--------20--------30--------40--------50--------60--------70--------80
        COMMENT_MAP.put(PROPERTY_TARGET,
                "# Project target.\n");
        COMMENT_MAP.put(PROPERTY_SPLIT_BY_DENSITY,
                "# Indicates whether an apk should be generated for each density.\n");
        COMMENT_MAP.put(PROPERTY_SDK,
                "# location of the SDK. This is only used by Ant\n" +
                "# For customization when using a Version Control System, please read the\n" +
                "# header note.\n");
        COMMENT_MAP.put(PROPERTY_APP_PACKAGE,
                "# The name of your application package as defined in the manifest.\n" +
                "# Used by the 'uninstall' rule.\n");
    }

    private final String mProjectFolderOsPath;
    private final Map<String, String> mProperties;
    private final PropertyType mType;

    /**
     * Loads a project properties file and return a {@link ProjectProperties} object
     * containing the properties
     *
     * @param projectFolderOsPath the project folder.
     * @param type One the possible {@link PropertyType}s.
     */
    public static ProjectProperties load(String projectFolderOsPath, PropertyType type) {
        File projectFolder = new File(projectFolderOsPath);
        if (projectFolder.isDirectory()) {
            File defaultFile = new File(projectFolder, type.mFilename);
            if (defaultFile.isFile()) {
                Map<String, String> map = SdkManager.parsePropertyFile(defaultFile, null /* log */);
                if (map != null) {
                    return new ProjectProperties(projectFolderOsPath, map, type);
                }
            }
        }
        return null;
    }

    /**
     * Merges all properties from the given file into the current properties.
     * <p/>
     * This emulates the Ant behavior: existing properties are <em>not</em> overriden.
     * Only new undefined properties become defined.
     * <p/>
     * Typical usage:
     * <ul>
     * <li>Create a ProjectProperties with {@link PropertyType#BUILD}
     * <li>Merge in values using {@link PropertyType#DEFAULT}
     * <li>The result is that this contains all the properties from default plus those
     *     overridden by the build.properties file.
     * </ul>
     *
     * @param type One the possible {@link PropertyType}s.
     * @return this object, for chaining.
     */
    public ProjectProperties merge(PropertyType type) {
        File projectFolder = new File(mProjectFolderOsPath);
        if (projectFolder.isDirectory()) {
            File defaultFile = new File(projectFolder, type.mFilename);
            if (defaultFile.isFile()) {
                Map<String, String> map = SdkManager.parsePropertyFile(defaultFile, null /* log */);
                if (map != null) {
                    for(Entry<String, String> entry : map.entrySet()) {
                        String key = entry.getKey();
                        String value = entry.getValue();
                        if (!mProperties.containsKey(key) && value != null) {
                            mProperties.put(key, value);
                        }
                    }
                }
            }
        }
        return this;
    }

    /**
     * Creates a new project properties object, with no properties.
     * <p/>The file is not created until {@link #save()} is called.
     * @param projectFolderOsPath the project folder.
     * @param type
     */
    public static ProjectProperties create(String projectFolderOsPath, PropertyType type) {
        // create and return a ProjectProperties with an empty map.
        return new ProjectProperties(projectFolderOsPath, new HashMap<String, String>(), type);
    }

    /**
     * Sets a new properties. If a property with the same name already exists, it is replaced.
     * @param name the name of the property.
     * @param value the value of the property.
     */
    public void setProperty(String name, String value) {
        mProperties.put(name, value);
    }

    /**
     * Sets the target property to the given {@link IAndroidTarget} object.
     * @param target the Android target.
     */
    public void setAndroidTarget(IAndroidTarget target) {
        assert mType == PropertyType.DEFAULT;
        mProperties.put(PROPERTY_TARGET, target.hashString());
    }

    /**
     * Returns the value of a property.
     * @param name the name of the property.
     * @return the property value or null if the property is not set.
     */
    public String getProperty(String name) {
        return mProperties.get(name);
    }

    /**
     * Removes a property and returns its previous value (or null if the property did not exist).
     * @param name the name of the property to remove.
     */
    public String removeProperty(String name) {
        return mProperties.remove(name);
    }

    /**
     * Saves the property file, using UTF-8 encoding.
     * @throws IOException
     */
    public void save() throws IOException {
        File toSave = new File(mProjectFolderOsPath, mType.mFilename);

        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(toSave),
                SdkConstants.INI_CHARSET);

        // write the header
        writer.write(mType.mHeader);

        // write the properties.
        for (Entry<String, String> entry : mProperties.entrySet()) {
            String comment = COMMENT_MAP.get(entry.getKey());
            if (comment != null) {
                writer.write(comment);
            }
            String value = entry.getValue();
            if (value != null) {
                value = value.replaceAll("\\\\", "\\\\\\\\");
                writer.write(String.format("%s=%s\n", entry.getKey(), value));
            }
        }

        // close the file to flush
        writer.close();
    }

    /**
     * Private constructor.
     * <p/>
     * Use {@link #load(String, PropertyType)} or {@link #create(String, PropertyType)}
     * to instantiate.
     */
    private ProjectProperties(String projectFolderOsPath, Map<String, String> map,
            PropertyType type) {
        mProjectFolderOsPath = projectFolderOsPath;
        mProperties = map;
        mType = type;
    }
}
