from hitchserve import Service
from os.path import join
import signal
import shutil
import sys



class PostgresDatabase(object):
    def __init__(self, name, owner, dump=None):
        self.name = name
        self.owner = owner
        self.dump = dump

    def psql(self, command=None):
        """Run PSQL command on this database."""
        return self.database_of.psql(command=command, database=self.name)

    def pg_dump(self, filename=None):
        """Dump this database to 'filename'."""
        return self.database_of.pg_dump(filename, database=self.name)

    @property
    def database_of(self):
        return self._database_of

    @database_of.setter
    def database_of(self, value):
        self._database_of = value

class PostgresUser(object):
    def __init__(self, username, password):
        self.username = username
        self.password = password

class PostgresService(Service):
    stop_signal = signal.SIGQUIT

    def __init__(self, postgres_package, port=15432, encoding='UTF-8', locale='en_US', pgdata=None, users=None, databases=None, **kwargs):
        #self.version = version
        self.postgres_package = postgres_package
        self.encoding = encoding
        self.locale = locale
        self.port = port
        #self.pg_installation = PostgresInstallation() if None else postgres_installation
        self.users = users
        self.databases = databases
        self.pgdata = pgdata
        kwargs['log_line_ready_checker'] = lambda line: "database system is ready to accept connections" in line
        super(PostgresService, self).__init__(**kwargs)

    @property
    def databases(self):
        return self._databases

    @databases.setter
    def databases(self, value):
        self._databases = value
        if self.databases is not None:
            for database in self._databases:
                database.database_of = self

    @property
    def pgdata(self):
        if self._pgdata is None:
            return join(self.service_group.hitch_dir.hitch_dir, 'pgdata')
        else:
            return self._pgdata

    @pgdata.setter
    def pgdata(self, value):
        self._pgdata = value

    @Service.command.getter
    def command(self):
        if self._command is None:
            return [self.postgres_package.postgres,
                '-p', str(self.port),
                '-D', self.pgdata,
                '--unix_socket_directories=' + self.pgdata,
                "--log_destination=stderr",]
        else:
            return self._command

    def setup(self):
        #self.log("Checking postgresql version...")
        #version_output = self.subcommand(self.pg_installation.exec_postgres, "--version").run(check_output=True)
        #if self.version not in version_output:
            #raise HitchException("Postgres version needed is {}, output is: {}.".format(self.version, version_output))
        self.log("Initializing postgresql database...")
        shutil.rmtree(self.pgdata, ignore_errors=True)
        # TODO : Put back encoding + locale
        self.subcommand(self.postgres_package.initdb, self.pgdata).run()

    def poststart(self):
        self.log("Creating users and databases...")
        for user in self.users:
            self.psql(
                """create user {} with password '{}';""".format(user.username, user.password)
            ).run()
        for database in self.databases:
            self.psql(
                """create database {} with owner {};""".format(
                    database.name, database.owner.username
                )
            ).run()
            if database.dump is not None:
                self.psql(database=database.name, filename=database.dump).run()

    def psql(self, command=None, database="template1", filename=None):
        """Run PSQL command."""
        fullcmd = [
            self.postgres_package.psql, "-d", database, "-p", str(self.port), "--host", self.pgdata,
        ]
        if command is not None:
            fullcmd = fullcmd + ["-c", command, ]
        if filename is not None:
            fullcmd = fullcmd + ["-f", filename, ]
        return self.subcommand(*fullcmd)

    def pg_dump(self, filename=None, database="template1"):
        """Dump a database."""
        fullcmd = [
            self.postgres_package.pg_dump, "-d", database, "-p",
            str(self.port), "--host", self.pgdata,
        ]
        if filename is not None:
            fullcmd = fullcmd + ["-f", filename, ]
        return self.subcommand(*fullcmd)

    def pg_restore(self, filename, database="template1"):
        """Restore a database."""
        fullcmd = [
            self.postgres_package.pg_restore, "-d", database, "-p",
            str(self.port), "--host", self.pgdata, filename
        ]
        return self.subcommand(*fullcmd)

@@ -3796,36 +3796,66 @@
 %22%22%22%0A        
-fullcmd = %5B%0A
+return self.subcommand(%0A            %5B%0A    
             
@@ -3881,16 +3881,32 @@
 ge.psql,
+%0A               
  %22-d%22, d
@@ -3971,99 +3971,135 @@
     
-%5D%0A        if command is not None:%0A            fullcmd = fullcmd +
+    %5D + (%0A                %5B%22-c%22, command, %5D if command is not None else %5B%5D%0A            ) + (%0A               
  %5B%22-
-c%22, command, %5D%0A       
+f%22, filename, %5D
  if 
@@ -4110,33 +4110,40 @@
 name is not None
-:
+ else %5B%5D
 %0A            ful
@@ -4143,86 +4143,18 @@
     
-fullcmd = fullcmd + %5B%22-f%22, filename, %5D%0A        return self.subcommand(*fullcmd
+)%0A        
 )%0A%0A 
@@ -4247,36 +4247,66 @@
 %22%22%22%0A        
-fullcmd = %5B%0A
+return self.subcommand(%0A            %5B%0A    
             
@@ -4335,16 +4335,32 @@
 pg_dump,
+%0A               
  %22-d%22, d
@@ -4369,36 +4369,24 @@
 abase, %22-p%22,
-%0A           
  str(self.po
@@ -4421,25 +4421,60 @@
         
-%5D%0A       
+    %5D + (%0A                %5B%22-f%22, filename, %5D
  if file
@@ -4481,35 +4481,41 @@
 name is not None
-:%0A 
+ else %5B%5D%0A
            fullc
@@ -4513,86 +4513,19 @@
     
-fullcmd = fullcmd + %5B%22-f%22, filename, %5D%0A        return self.subcommand(*fullcmd
+ )%0A        
 )%0A%0A 
@@ -4627,18 +4627,31 @@
     
-fullcmd = 
+return self.subcommand(
 %5B%0A  
@@ -4789,46 +4789,6 @@
    %5D
-%0A        return self.subcommand(*fullcmd
 )%0A

REFACTOR : Cleaned up subcommands.