/*
 * Copyright 2013 Maksim Kisilyov
 *
 * 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.luxoft.p4ctm;

import java.io.*;
import java.util.Properties;

public class CTMBuilderOptions
{
    private String server;
    private String user;
    private String password;
    private String fileSpec;
    private String requirementIdRegex;
    private String typeOfChangeRegex;
    private String acceptedTypesOfChangeRegex;
    private String clDescriptionsOverridePath;
    private String requirementsInputFile;
    private String requirementsInputRegex;
    private String requirementsFilterFile;
    private String matrixOutputFile;


    public CTMBuilderOptions()
    {
        this.server = "perforce:1666";
        this.user = "anonymous";
        this.password = "";
        this.fileSpec = "//depot/...";
        this.requirementIdRegex = "(?m)^\\[[xX]\\] TTS/Ref : (.*?)\\s*?$";
        this.typeOfChangeRegex = "(?m)^\\[[xX]\\] (?:BF|FE|OP|QI|IN|OT) = (.*?)\\s*?$";
        this.acceptedTypesOfChangeRegex = "BugFix|Feature";
        this.clDescriptionsOverridePath = null;
        this.requirementsInputFile = null;
        this.requirementsInputRegex = "(?ms)CTRS ID:  (?<rid>.*?)$.*?Object Heading:  (?<name>.*?)$.*?Object Text:  (?<desc>.*?)$";
        this.requirementsFilterFile = null;
        this.matrixOutputFile = "TM.xls";
    }

    public CTMBuilderOptions(String server, String user, String password, String fileSpec,
                             String requirementIdSearchPattern, String typeOfChangeRegex,
                             String acceptedTypesOfChangeRegex, String CLDescriptionsInputPath,
                             String requirementsInputFile, String requirementsInputRegex,
                             String requirementsFilterFile, String matrixOutputFile)
    {
        this.server = server;
        this.user = user;
        this.password = password;
        this.fileSpec = fileSpec;
        this.requirementIdRegex = requirementIdSearchPattern;
        this.typeOfChangeRegex = typeOfChangeRegex;
        this.acceptedTypesOfChangeRegex = acceptedTypesOfChangeRegex;
        this.clDescriptionsOverridePath = CLDescriptionsInputPath;
        this.requirementsInputFile = requirementsInputFile;
        this.requirementsInputRegex = requirementsInputRegex;
        this.requirementsFilterFile = requirementsFilterFile;
        this.matrixOutputFile = matrixOutputFile;
    }

    public void loadFromXML(File input) throws IOException
    {
        new XMLIO().readXML(input);
    }

    public void storeToXML(File output) throws IOException
    {
        new XMLIO().writeXML(output);
    }

    public String getServer()
    {
        return server;
    }

    public String getUser()
    {
        return user;
    }

    public String getPassword()
    {
        return password;
    }

    public void setPassword(String password)
    {
        this.password = password;
    }

    public String getFileSpec()
    {
        return fileSpec;
    }

    public String getRequirementIdRegex()
    {
        return requirementIdRegex;
    }

    public String getTypeOfChangeRegex()
    {
        return typeOfChangeRegex;
    }

    public String getAcceptedTypesOfChangeRegex()
    {
        return acceptedTypesOfChangeRegex;
    }

    public String getCLDescriptionsOverridePath()
    {
        return clDescriptionsOverridePath;
    }

    public String getRequirementsInputFile()
    {
        return requirementsInputFile;
    }

    public String getRequirementsInputRegex()
    {
        return requirementsInputRegex;
    }

    public String getRequirementsFilterFile()
    {
        return requirementsFilterFile;
    }

    public String getMatrixOutputFile()
    {
        return matrixOutputFile;
    }

    private interface Archive
    {
        String fill(String key, String value);
    }

    private class XMLIO extends Properties
    {
        private void serialize(Archive archive)
        {
            server = archive.fill("server", server);
            user = archive.fill("user", user);
            fileSpec = archive.fill("file spec", fileSpec);
            requirementIdRegex = archive.fill("requirement id regex", requirementIdRegex);
            typeOfChangeRegex = archive.fill("type of change regex", typeOfChangeRegex);
            acceptedTypesOfChangeRegex = archive.fill("accepted types of change regex", acceptedTypesOfChangeRegex);
            clDescriptionsOverridePath = archive.fill("cl descriptions override path", clDescriptionsOverridePath);
            requirementsInputFile = archive.fill("requirements input file", requirementsInputFile);
            requirementsInputRegex = archive.fill("requirements input regex", requirementsInputRegex);
            requirementsFilterFile = archive.fill("requirements filter file", requirementsFilterFile);
            matrixOutputFile = archive.fill("output file", matrixOutputFile);
        }

        public void readXML(File file) throws IOException
        {
            try (InputStream inputStream = new FileInputStream(file))
            {
                loadFromXML(inputStream);
                serialize(new InputArchive());
            }
        }

        public void writeXML(File file) throws IOException
        {
            try (OutputStream outputStream = new FileOutputStream(file))
            {
                serialize(new OutputArchive());
                storeToXML(outputStream, null);
            }
        }

        private class InputArchive implements Archive
        {
            @Override
            public String fill(String key, String value)
            {
                return getProperty(key);
            }
        }

        private class OutputArchive implements Archive
        {
            @Override
            public String fill(String key, String value)
            {
                if (key == null || value == null)
                {
                    return null;
                }

                setProperty(key, value);
                return value;
            }
        }
    }
}
