from parallels.core.hosting_repository.database import DatabaseModel, DatabaseEntity
from parallels.core.utils.common import is_empty
from parallels.plesk.hosting_repository.base import PleskBaseModel
from parallels.plesk.hosting_repository.utils.cli.database import DatabaseCreateCli, DatabaseRegisterCli


class PleskDatabaseModel(DatabaseModel, PleskBaseModel):
    def create_from_dump(self, database_dump, subscription_name, is_assimilate=False):
        """Create database in target Plesk

        :type database_dump: parallels.core.dump.data_model.Database
        :type subscription_name: str
        :type is_assimilate: bool
        """
        if is_assimilate:
            command = DatabaseRegisterCli(
                runner=self.plesk_cli_runner,
                database_name=database_dump.name,
                database_type=database_dump.dbtype,
                database_host=database_dump.host,
                database_port=database_dump.port,
                subscription_name=subscription_name
            )
        else:
            command = DatabaseCreateCli(
                runner=self.plesk_cli_runner,
                database_name=database_dump.name,
                database_type=database_dump.dbtype,
                database_host=database_dump.host,
                database_port=database_dump.port,
                subscription_name=subscription_name
            )
        command.run()

    def create(self, database, subscription_name):
        """Create database in target panel

        :type database: parallels.core.hosting_repository.database.CreateDatabaseEntity
        :type subscription_name: str | unicode
        :rtype: None
        """
        command = DatabaseCreateCli(
            runner=self.plesk_cli_runner,
            database_name=database.name,
            database_type=database.dbtype,
            database_host=database.host,
            database_port=database.port,
            subscription_name=subscription_name
        )
        command.run()

    def is_exists_by_subscription(self, subscription_name, database_name):
        """Check if database with given name exists in target Plesk

        :type subscription_name: str
        :type database_name: str
        :rtype: bool
        """
        result = self.plesk_server.query_panel_db(
            'SELECT id FROM data_bases WHERE name = %(database_name)s', dict(
                database_name=database_name
            )
        )
        return len(result) > 0

    def get_list_by_subscription(self, subscription_name, db_type):
        """Retrieve list of databases in panel for given subscription

        :type subscription_name: str | unicode
        :type db_type: str | unicode
        :rtype: list[parallels.core.hosting_repository.database.DatabaseEntity]
        """
        query = """
          SELECT data_bases.name, db_users.login FROM domains
            JOIN data_bases ON data_bases.dom_id = domains.id
            LEFT JOIN db_users ON (
              db_users.dom_id = domains.id AND
              (db_users.db_id = data_bases.id OR db_users.db_id = 0 OR db_users.db_id IS NULL)
            )
            WHERE domains.name = %(domain_name)s AND type = %(db_type)s
        """
        result = self.plesk_server.query_panel_db(
            query, dict(
                domain_name=subscription_name.encode('idna'),
                db_type=db_type
            )
        )
        databases_dict = {}
        for row in result:
            db_name = row['name']
            db_user_login = row['login']
            if db_name not in databases_dict:
                databases_dict[db_name] = []
            if not is_empty(db_user_login):
                databases_dict[db_name].append(db_user_login)

        databases = []
        for database_name, database_users in databases_dict.items():
            databases.append(DatabaseEntity(
                name=database_name, user_names=database_users
            ))

        return databases
