'''
/***************************************************************************
Name	   :  workspace_setup_model.py
Description:  Setup (workspace) model class for FEWSTools plugin,
              updated from QGIS2
copyright  :  (C) 2019-2023 by FEWS
email      :  minxuansun@contractor.usgs.gov
Created    :  10/15/2019 - cholen
Modified   :  12/31/1019 - cholen - Added method to get output path
              02/07/2020 - cholen - Added fix_os_sep_in_path
              10/08/2020 - cholen - Removed duplicate function
              02/22/2021 - cholen - Add initialize_default_output_dir
              07/25/2022 - cholen - Add migrate_workspace_table
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
'''
import os
from pathlib import Path

from fews_tools import fews_tools_config as config
from fews_tools.utilities import database_utilities as db_util


class WorkspaceSetupModel:
    '''
    Class to hold setup(workspace) information.
    '''
    def __init__(self):
        self.setup_table_name = 'WorkspaceSetup'
        self.setup_fields = None
        self.static_data_path = None
        self.archive_data_path = None
        self.output_path = None
        self.map_data_path = None
        self.climate_data_path = None
        self.colors_path = None
        self.temp_path = None
        sql = 'SELECT Workspace FROM ' + self.setup_table_name
        # this query will return a tuple, grab the 0 element for the string
        sql_result = db_util.query_db(sql)
        self.workspace = sql_result[0]

        # get default output directory form database
        columns = self.get_current_columns_from_table()
        if 'OutputDir' in columns:
            sql = 'SELECT OutputDir FROM ' + self.setup_table_name
            # this query will return a tuple, grab the 0 element for the string
            sql_result = db_util.query_db(sql)
            self.output_path = self.fix_os_sep_in_path(sql_result[0])
        else:
            self.output_path = os.path.join(self.workspace, 'Output')

        if self.workspace:
            self.set_data_paths()

    def get_climate_data_path(self):
        '''
        Function to get the data path.
        '''
        return self.climate_data_path

    def get_colors_path(self):
        '''
        Function to get the colors(styles) path.
        '''
        return self.colors_path

    def get_map_data_path(self):
        '''
        Function to get the map data path.
        '''
        return self.map_data_path

    def get_static_data_path(self):
        '''
        Function to get the static(mask) data path.
        '''
        return self.static_data_path

    def get_archive_data_path(self):
        '''
        Function to get archive data path.
        '''
        return self.archive_data_path

    def get_output_path(self):
        '''
        Function to get output path.
        '''
        return self.output_path

    def get_temp_data_path(self):
        '''
        Funtion to get the temp data path.
        '''
        return self.temp_path

    def get_workspace(self):
        '''
        Function to get the workspace value.
        '''
        return self.workspace

    def fix_os_sep_in_path(self, src_path):
        '''
        Gets the os.sep straightened out
        params(string) - src_path - Source filename
        '''
        ret_path = ''
        if '/' in src_path and os.sep != '/':
            ret_path = src_path.replace('/', os.sep)
        elif '\\' in src_path and os.sep != '\\':
            ret_path = src_path.replace('\\', os.sep)
        else:
            ret_path = src_path
        return ret_path

    def initialize_default_output_dir(self, default_workspace):
        ''''
        Function to set the OutputDir value to inital default value,
        needs to be a variable name because will be users area.
        Args:
            default_workspace(string) - Default(first deployed) workspace path
        '''
        # there should only ever be one record here...
        default_output_dir = self.fix_os_sep_in_path(
            os.path.join(default_workspace, 'Output'))
        sql = "UPDATE {} SET OutputDir='{}'".format(
            self.setup_table_name, default_output_dir)
        db_util.write_db(sql)
        self.output_path = default_output_dir

    def set_workspace(self, workspace_path):
        '''
        Function to set the workspace value in the database.
        Args:
            workspace_path(string) - New workspace path.
        '''
        workspace_path = self.fix_os_sep_in_path(workspace_path)
        if workspace_path[-1] != os.sep:
            param = [workspace_path + os.sep]
        else:
            param = [workspace_path]

        sql = 'SELECT * FROM ' + self.setup_table_name
        qry_result = db_util.query_db(sql)[0]
        if qry_result:
            sql_write = ('UPDATE ' + self.setup_table_name +
                         ' SET Workspace = ?')
        else:  # this should never happen but it's a safeguard
            sql_write = ('INSERT INTO ' + self.setup_table_name +
                         ' (Workspace) VALUES(?)')
        db_util.write_db(sql_write, param)
        self.workspace = workspace_path
        self.set_data_paths()

    def set_output_dir(self, old_workspace_path, new_workspace_path):
        ''''
        Function to set the OutputDir value in the database,
        based on new workspace path.
        Args:
            old_workspace_path(string) - old workspace path.
            new_workspace_path(string) - new workspace path
        '''
        old_workspace_path = self.fix_os_sep_in_path(old_workspace_path)
        if old_workspace_path[-1] != os.sep:
            old_workspace_path = old_workspace_path + os.sep
        new_workspace_path = self.fix_os_sep_in_path(new_workspace_path)
        if new_workspace_path[-1] != os.sep:
            new_workspace_path = new_workspace_path + os.sep
        sql = 'SELECT OutputDir FROM ' + self.setup_table_name
        qry_result = db_util.query_db(sql)[0]
        if qry_result:
            output_dir = self.fix_os_sep_in_path(qry_result)
            if Path(old_workspace_path) in Path(output_dir).parents:
                # if output dir is in workspace dir,
                # update it to point to the new workspace
                output_dir = \
                    output_dir.replace(old_workspace_path, new_workspace_path)
                sql_write = ('UPDATE ' + self.setup_table_name +
                             " SET OutputDir = '{}' ".format(output_dir))
                db_util.write_db(sql_write)
                self.output_path = output_dir
        else:  # this should never happen but it's a safeguard
            output_dir = os.path.join(new_workspace_path, 'Output')
            sql_write = "INSERT INTO {} (OutputDir) VALUES ({});".format(
                self.setup_table_name, output_dir)
            db_util.write_db(sql_write)
            self.output_path = output_dir

    def set_data_paths(self):
        '''
        Construct data paths from workspace and config
        '''
        self.climate_data_path = self.fix_os_sep_in_path(os.path.join(
            self.workspace,
            config.PROGRAM_SETTINGS,
            config.DATA,
            config.CLIMATE))

        self.colors_path = self.fix_os_sep_in_path(os.path.join(
            self.workspace,
            config.PROGRAM_SETTINGS,
            config.COLORS))

        self.temp_path = self.fix_os_sep_in_path(os.path.join(
            self.workspace,
            config.PROGRAM_SETTINGS,
            config.TEMP))

        self.map_data_path = self.fix_os_sep_in_path(os.path.join(
            self.workspace,
            config.PROGRAM_SETTINGS,
            config.DATA,
            config.MAPS))

        self.static_data_path = self.fix_os_sep_in_path(os.path.join(
            self.workspace,
            config.PROGRAM_SETTINGS,
            config.DATA,
            config.STATIC))

    def add_default_output_dir_to_table(self):
        '''
        add a output dir column to WorkspaceSetup table
        later can remove this function when all users have this column in their
        database
        '''
        col_names = self.get_current_columns_from_table()
        if 'OutputDir' not in col_names:
            sql_write = ("ALTER TABLE " + self.setup_table_name +
                         " ADD COLUMN 'OutputDir' TEXT")
            db_util.write_db(sql_write)
            # add default value in
            default_output_dir = \
                self.fix_os_sep_in_path(os.path.join(self.workspace, 'Output'))
            sql_write = \
                ("UPDATE " + self.setup_table_name +
                 " SET OutputDir = '{}' WHERE Workspace = '{}'".format(
                     default_output_dir, self.workspace))
            db_util.write_db(sql_write)
            self.output_path = default_output_dir

    def get_current_columns_from_table(self):
        '''
        Get the current columns from the table
        '''
        sql_query = ("SELECT * FROM " + self.setup_table_name)
        col_names = db_util.query_db_columns(sql_query)
        return col_names

    def migrate_workspace_table(self):
        '''
        Moves the Workspace setup(single row)row to the new database
        '''
        # get old db values
        sql_query = ("SELECT * FROM " + self.setup_table_name)
        old_qry_result = db_util.query_db(
            sql_query, None, True, config.OLD_DB_FILE)
        params = old_qry_result[0]

        # remove new db values
        new_db_qry_result = db_util.query_db(
            sql_query, None, True, config.DB_FILE)
        if new_db_qry_result:
            sql_delete = ("DELETE FROM " + self.setup_table_name)
            db_util.write_db(sql_delete, None, config.DB_FILE)
        # write old db values to new db
        sql_write = ("INSERT INTO " + self.setup_table_name +
                     " (Workspace, OutputDir) VALUES(?,?)")
        db_util.write_db(sql_write, params, config.DB_FILE)
