using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using dataladder.Data;
using dataladder.Matching;
using dataladder.Licensing;
using dataladder.Matching.Project;
using dataladder.Data.DataTransformation;
using dataladder.XtraGridHelper;


namespace UsingTheExistingProjectWithGUI
{
    public partial class MainForm : Form
    {
        #region Fields

        string engineConfigurationIniFileName = "configuration.ini";
        string appPath;

        #endregion

        #region Constructors

        public MainForm()
        {
            InitializeComponent();
            appPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
        }

        #endregion

        #region Methods

        void updateStatus(string text)
        {
            infoTextBox.Text += text + "\r\n";
            Application.DoEvents();
        }

        private void openProject()
        {
            string fullIniName = System.IO.Path.Combine(appPath, engineConfigurationIniFileName);
            IniParser parser = new IniParser(fullIniName);
            string projectsPath = parser.GetSetting("AppSettings", "projectsPath");
            projectOpenFileDialog.InitialDirectory = projectsPath;
            if (projectOpenFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string projectFileName = projectOpenFileDialog.FileName;
                string projectName = System.IO.Path.GetFileNameWithoutExtension(projectFileName);
                projectNameTextBox.Text = projectFileName;

                string pathForRegistrationFile = parser.GetSetting("AppSettings", "pathForRegistrationFile");
                string dataPath = parser.GetSetting("AppSettings", "dataPath");
                string tempDataPath = parser.GetSetting("AppSettings", "tempDataPath");
                string accuPath = parser.GetSetting("AppSettings", "accuPath");
                string geoPath = parser.GetSetting("AppSettings", "geoPath");

                String connString = parser.GetSetting("AppSettings", "connectionString");
                connString = connString.Trim('\'');

                RegistrationWrapper registrationWrapper = new RegistrationWrapper();
                registrationWrapper.CustomPathForRegistrationFile = pathForRegistrationFile;
                DateTime expirationTime = RegistrationWrapper.ExpirationDate;
                updateStatus("Expiration time: " + expirationTime.ToString());

                dataladder.Matching.ApplicationSettings.DataPath = dataPath;
                dataladder.Matching.ApplicationSettings.TempDataPath = tempDataPath;
                dataladder.Matching.ApplicationSettings.AccuPath = accuPath + @"\";
                dataladder.Matching.ApplicationSettings.GeoCodePath = geoPath + @"\";

                ProjectInfo projectInfo = new ProjectInfo();
                projectInfo.Load(projectFileName);
                updateStatus("project: \"" + projectInfo.ProjectName + "\" loaded.");
                projectInfo.RunTransformation();
                updateStatus("data transformed");
                projectInfo.MatchEngine.DoIndex();
                updateStatus("indexing finished");
                projectInfo.MatchEngine.DoMatch();
                updateStatus("matching finished");
                projectInfo.MatchEngine.ProcessFinalResults();
                updateStatus("results processed");

                DataSourceInfo dataSourceInfo = projectInfo[0];                
                SqlDbHelper sqlDbHelper = new SqlDbHelper(connString);
                string exportTableName = dataSourceInfo.Name + " groups";
                string schemaName = "dbo";

                string[] columnNamesToRemove =
                {
                    "Group ID",
                    "Match Definition",
                    "Data Source",
                    "Data Source Name",
                    "Record",
                    "Matching Data Source",
                    "Matching Record",
                    "Master",
                    "Selected",
                    "Not Duplicate",
                    "Score",
                    "TaxNumber score"
                };
                ColumnsFilter groupsColumnsFilter =
                    getColumnsFilter(projectInfo.MatchEngine.FinalScoresGroupsTable, columnNamesToRemove);
                ColumnsFilter pairsColumnsFilter =
                    getColumnsFilter(projectInfo.MatchEngine.PairsScoresTable, columnNamesToRemove);

                bool tableExists = dropTableIfExists(sqlDbHelper, exportTableName, schemaName);
                dataladder.Data.IReaderHelper.Export(groupsColumnsFilter,
                    sqlDbHelper,
                    schemaName: "",
                    tableName: exportTableName,
                    onTableProgress: null,
                    truncate: false,
                    bulkCopy: true);
                string exportPairsTableName = dataSourceInfo.Name + " pairs";
                tableExists = dropTableIfExists(sqlDbHelper, exportPairsTableName, schemaName);
                dataladder.Data.IReaderHelper.Export(pairsColumnsFilter,
                    sqlDbHelper,
                    schemaName: "",
                    tableName: exportPairsTableName,
                    onTableProgress: null,
                    truncate: false,
                    bulkCopy: true);
                projectInfo.Dispose();
                updateStatus("data exported");
            }
        }

        ColumnsFilter getColumnsFilter(ITable2CoordsMapper table, string[] columnNamesToRemove)
        {
            List<string> filteredColumnNames = new List<string>();
            string[] allColumnNames = table.GetColumnNames();
            for (int i = 0; i < allColumnNames.Length; i++)
            {
                string colName = allColumnNames[i];
                if (!columnNamesToRemove.Contains(colName))
                {
                    filteredColumnNames.Add(colName);
                }
            }
            ColumnsFilter result = new ColumnsFilter(filteredColumnNames, table);
            return result;
        }

        private static bool dropTableIfExists(SqlDbHelper sqlDbHelper, string exportTableName, string schemaName)
        {
            bool tableExists = sqlDbHelper.TableExists(schemaName, exportTableName);
            if (tableExists)
            {
                sqlDbHelper.DropTable("[" + exportTableName + "]");
            }
            return tableExists;
        }

        #endregion

        #region Events and Handlers

        private void openProjectButton_Click(object sender, EventArgs e)
        {
            openProject();
        }

        #endregion

    }
}
