#!/usr/local/bin/python

import cmd
import getopt
import os
import re
import string
import sys

sys.path.extend([
    '/usr/local/www',
    '/usr/local/www/freenasUI'
])

os.environ["DJANGO_SETTINGS_MODULE"] = "freenasUI.settings"

from django.db.models.loading import cache
cache.get_apps()

from freenasUI.common.freenasldap import (
    FreeNAS_ActiveDirectory,
    FLAGS_DBINIT
)

from freenasUI.directoryservice.models import ActiveDirectory


class ActiveDirectoryConfig(FreeNAS_ActiveDirectory):
    pass


class ADToolShell(cmd.Cmd):
    prompt = "adtool> "

    def __init__(self, **kwargs):
        cmd.Cmd.__init__(self)
        try:
            self.adc = ActiveDirectoryConfig(flags=FLAGS_DBINIT)
        except Exception as e:
            print >> sys.stderr, "ERROR: %s" % e
            sys.exit(1)

        self.ado = ActiveDirectory.objects.all()[0]
        self.flags = 0

    def cmdloop(self, intro=None):
        return cmd.Cmd.cmdloop(self, intro)

    def onecmd(self, line):
        return cmd.Cmd.onecmd(self, line)

    def emptyline(self):
        pass

    def default(self, line):
        tmp = line.strip() 
        if tmp.startswith('#'):
            return
        return cmd.Cmd.default(self, line)

    def do_help(self, arg):
        options = [
            [ "config_file", "Generate configf file" ],
            [ "verbose_logging", "Verbose logging" ],
            [ "timeout", "Timeout for commands" ],
            [ "dns_timeout", "DNS query timeout" ],
            [ "bindname", "Name to bind as" ],
            [ "domainname", "Name of domain"],
            [ "basedn", "Base DN" ],
            [ "binddn", "Bind DN"],
            [ "netbiosname", "Netbios name of the domain" ],
            [ "workgroup", "Netbios name of the domain" ],
            [ "site", "Domain site" ],
            [ "dcname", "Domain controller in hostname:port format" ],
            [ "dchost", "Domain controller hostname" ],
            [ "dcport", "Domain controller port" ],
            [ "gcname", "Global catalog server in hostname:port format" ],
            [ "gchost", "Global catalog server hostname" ],
            [ "gcport", "Global catalog server port" ],
            [ "krbname", "Kerberos server in hostname:port format" ],
            [ "krbhost", "Kerberos server hostname" ],
            [ "krbport", "Kerberos server port" ],
            [ "kpwdname", "Kerberos password change server in hostname:port format"],
            [ "kpwdhost", "Kerberos password change server hostname" ],
            [ "kpwdport", "Kerberos password change server port" ],
            [ "krb_realm", "Kerberos realm" ],
            [ "krb_kdc", "Kerberos KDC" ],
            [ "krb_admin_server", "Kerberos admin server" ],
            [ "krb_kpasswd_server", "Kerberos password server" ],
            [ "keytab_name", "Kerberos keytab name" ],
            [ "keytab_principal", "Kerberos keytab principal" ],
            [ "keytab_file", "Kerberos keytab file" ],
            [ "ssl", "SSL/TLS value" ],
            [ "certificate", "SSL/TLS Certificate path" ],
            [ "rootDSE", "Root of domain" ],
            [ "config", "Configuration DN" ],
            [ "partitions", "Directory partitions" ],
            [ "root_domain", "Root domain" ],
            [ "domain", "Domain" ],
            [ "domains", "Available domains" ],
            [ "ldap_servers", "LDAP servers for domain" ],
            [ "domain_controllers", "Domain controllers for domain" ],
            [ "primary_domain_controllers", "Primary domain controllers for domain" ],
            [ "global_catalog_servers", "Global catalog servers for domain" ],
            [ "forest_global_catalog_servers", "Global catalog servers for forst" ],
            [ "kerberos_servers", "Kerberos servers for domain" ],
            [ "kerberos_domain_controllers", "Kerberos domain controllers for domain" ],
            [ "kpasswd_servers", "Kerberos password change servers for domain" ]
        ]

        print >> sys.stderr, """\
[set|get] <option> <value> [DOMAIN=domain.. SITE=site..]:
  eg: set dchost dc0.example.com
  eg: get dchost 
  eg: get dchost DOMAIN=example.com

Available options:
        """
        for opts in options:
            print >> sys.stderr, "  %-32s %s" % (opts[0], opts[1])

    def do_set(self, arg):
        args = arg.split()
        
        set_method = getattr(self, "set_%s" % args[0]) 
        if set_method:
            set_method(string.join(args[1:], ' '))

    def do_get(self, arg):
        args = arg.split()

        get_method = getattr(self, "get_%s" % args[0])
        if get_method:
            get_method(args)

    def do_debug(self, arg):
        pass

    def do_connect(self, arg):
        pass
    def do_join(self, arg):
        pass

    def do_save(self, arg):
        self.ado.save()
        self.adc.reload()

    def do_exit(self, arg):
        sys.exit(0)
    def do_quit(self, arg):
        sys.exit(0)

    def setbool(self, args):
        val = None 
        if arg == '0':
            val = False 
        elif arg.lower() == 'false':
            val = False 
        elif arg == '1':
            val = True
        if arg.lower() == 'true':
            val = True
        return val

    def get_config_file(self, args):
        keys = [
            "ad_bindname",
            "ad_domainname",
            "ad_netbiosname",
            "ad_basedn",
            "ad_binddn",
            "ad_site",
            "ad_dcname",
            "ad_dchost",
            "ad_dcport",
            "ad_gcname",
            "ad_gchost",
            "ad_gcport",
            "ad_krbname",
            "ad_krbhost",
            "ad_krbport",
            "ad_kpwdname",
            "ad_kpwdhost",
            "ad_kpwdport",
            "ad_krb_realm",
            "ad_krb_kdc",
            "ad_krb_admin_server",
            "ad_krb_kpasswd_server",
            "ad_keytab_name",
            "ad_keytab_principal",
            "ad_keytab_file",
            "ad_timeout",
            "ad_dns_timeout",
            "ad_certfile",
            "ad_ssl",
            "ad_unix_extensions"
        ]

        for k in keys:
            attr = k.replace("ad_", "")
            val = getattr(self.adc, attr)

            if val == True:
                val = 1
            if val == False:
                val = 0
            if re.match('\S+\s+', str(val)):
                val = "\"%s\"" % val

            print >> sys.stdout, "%s=%s" % (
                k, val if val != None else ''
            )

    def get_verbose_logging(self, args):
        print >> sys.stdout, self.adc.verbose_logging
    
    def set_verbose_logging(self, args):
        val = None
    
        ad = self.ado
        for arg in args:
            val = setbool(arg)
    
        if val != None:
            ad.ad_verbose_logging = val 
            ad.save()
    
    def get_timeout(self, args):
        print >> sys.stdout, self.adc.timeout
    
    def set_timeout(self, args):
        val = None
    
        ad = self.ado
        for arg in args:
            if not arg.isdigit():
                print >> sys.stderr, "not an integer"
                return
           
            val = long(arg)
    
        if val != None:
            ad.ad_timeout = val 
            ad.save()
    
    def get_dns_timeout(self, args):
        print >> sys.stdout, self.adc.dns_timeout
    
    def set_dns_timeout(self, args):
        val = None
    
        ad = self.ado
        for arg in args:
            if not arg.isdigit():
                print >> sys.stderr, "not an integer"
                return
           
            val = long(arg)
    
        if val != None:
            ad.ad_dns_timeout = val 
            ad.save()

    def get_ssl(self, args):
        print >> sys.stdout, self.adc.ssl

    def set_ssl(self, args):
        for arg in args:
            self.adc.ssl = arg

    def get_certificate(self, args):
        print >> sys.stdout, self.adc.certfile

    def set_certificate(self, args):
        for arg in args:
            self.adc.certfile = arg

    def get_bindname(self, args):
        print >> sys.stdout, self.adc.bindname

    def set_bindname(self, args):
        val = None
    
        ad = self.ado
        for arg in args:
            val = arg
    
        if val != None:
            ad.ad_bindname = val 
            ad.save()
    
    def get_domainname(self, args):
        print >> sys.stdout, self.adc.domainname

    def set_domainname(self, args):
        val = None
    
        ad = self.ado
        for arg in args:
            val = arg
    
        if val != None:
            ad.ad_domainname = val 
            ad.save()
    
    def get_basedn(self, args):
        print >> sys.stdout, self.adc.basedn

    def set_basedn(self, args):
        self.adc.basedn = args
        self.adc.reload() 
    
    def get_binddn(self, args):
        print >> sys.stdout, self.adc.binddn

    def set_binddn(self, args):
        pass

    def get_netbiosname(self, args):
        print >> sys.stdout, self.adc.netbiosname

    def set_netbiosname(self, args):
        for arg in args:
            self.adc.netbiosname = arg

    def get_workgroup(self, args):
        return self.get_netbiosname(args)

    def set_workgroup(self, args):
        return self.set_netbiosname(args)

    def get_site(self, args):
        print >> sys.stdout, self.adc.site

    def get_dcname(self, args):
        print >> sys.stdout, self.adc.dcname

    def set_dcname(self, args):
        for arg in args:
            self.adc.dcname = arg
    
    def get_dchost(self, args):
        print >> sys.stdout, self.adc.dchost

    def set_dchost(self, args):
        for arg in args:
            self.adc.dchost = arg
    
    def get_dcport(self, args):
        print >> sys.stdout, self.adc.dcport

    def set_dcport(self, args):
        for arg in args:
            self.adc.dcport = long(arg)
    
    def get_gcname(self, args):
        print >> sys.stdout, self.adc.gcname

    def set_gcname(self, args):
        for arg in args:
            self.adc.gcname = arg
    
    def get_gchost(self, args):
        print >> sys.stdout, self.adc.gchost

    def set_gchost(self, args):
        for arg in args:
            self.adc.gchost = arg
    
    def get_gcport(self, args):
        print >> sys.stdout, self.adc.gcport

    def set_gcport(self, args):
        for arg in args:
            self.adc.gcport = long(arg)

    def get_krbname(self, args):
        print >> sys.stdout, self.adc.krbname

    def set_krbname(self, args):
        for arg in args:
            self.adc.krbname = arg
    
    def get_krbhost(self, args):
        print >> sys.stdout, self.adc.krbhost

    def set_krbhost(self, args):
        for arg in args:
            self.adc.krbhost = arg
    
    def get_krbport(self, args):
        print >> sys.stdout, self.adc.krbport

    def set_krbport(self, args):
        for arg in args:
            self.adc.krbport = long(arg)
    
    def get_kpwdname(self, args):
        print >> sys.stdout, self.adc.kpwdname

    def set_kpwdname(self, args):
        for arg in args:
            self.adc.kpwdname = arg
    
    def get_kpwdhost(self, args):
        print >> sys.stdout, self.adc.kpwdhost

    def set_kpwdhost(self, args):
        for arg in args:
            self.adc.kpwdhost = arg
    
    def get_kpwdport(self, args):
        print >> sys.stdout, self.adc.kpwdport

    def set_kpwdport(self, args):
        for arg in args:
            self.adc.kpwdport = long(arg)
    
    def get_krb_realm(self, args):
        print >> sys.stdout, self.adc.krb_realm

    def set_krb_realm(self, args):
        for arg in args:
            self.adc.krb_realm = arg 

    def get_krb_kdc(self, args):
        print >> sys.stdout, self.adc.krb_kdc

    def set_krb_kdc(self, args):
        for arg in args:
            self.adc.krb_kdc = arg

    def get_krb_admin_server(self, args):
        print >> sys.stdout, self.adc.krb_admin_server

    def set_krb_admin_server(self, args):
        for arg in args:
            self.adc.krb_admin_server = arg

    def get_krb_kpasswd_server(self, args):
        print >> sys.stdout, self.adc.krb_kpasswd_server

    def set_krb_kpasswd_server(self, args):
        for arg in args:
            self.adc.krb_kpasswd_server = arg
   
    def get_keytab_name(self, args):
        print >> sys.stdout, self.adc.keytab_name

    def set_keytab_name(self, args):
        for arg in args:
            self.adc.keytab_name = arg
   
    def get_keytab_principal(self, args):
        print >> sys.stdout, self.adc.keytab_principal

    def set_keytab_principal(self, args):
        for arg in args:
            self.adc.keytab_principal = arg

    def get_keytab_file(self, args):
        print >> sys.stdout, self.adc.keytab_file

    def set_keytab_file(self, args):
        for arg in args:
            self.adc.keytab_file = arg

    def get_rootdse(self, args):
        results = self.adc.get_rootDSE()
        try:
            results = results[0][1] 
            for key in results:
                val = string.join(results[key], ' ')
                print >> sys.stdout, "%s: %s" % (key, val)
        except:
            pass

    def get_rootdn(self, args):
        print >> sys.stdout, self.adc.get_rootDN()

    def get_config(self, args):
        print >> sys.stdout, self.adc.get_config()

    def get_partitions(self, args):
        results = self.adc.get_partitions()
        try:
            for i in results:
                for key in i[1]:
                    val = string.join(i[1][key], ' ')
                    print >> sys.stdout, "%s: %s"  % (key, val)
                print >> sys.stdout, "\n"
        except:
            pass

    def get_root_domain(self, args):
        print >> sys.stdout, self.adc.get_root_domain()

    def get_domain(self, args):
        print >> sys.stdout, self.adc.get_domain()

    def get_domains(self, args):
        pass

    def domain_site_parse(self, args):
        domain = site = None

        for pair in args:
            parts = pair.split('=')
            if len(parts) > 1:
                if parts[0].lower() == 'domain':
                    domain = parts[1] 
                elif parts[0].lower() == 'site':
                    site = parts[1]

        return (domain, site)
    
    def get_ldap_servers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        ldap_servers = self.adc.get_ldap_servers(domain, site)
        for ldap_server in ldap_servers:
            print >> sys.stdout, ldap_server

    def set_ldap_servers(self, args):
        pass
    
    def get_domain_controllers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        domain_controllers = self.adc.get_domain_controllers(domain, site)
        for domain_controller in domain_controllers:
            print >> sys.stdout, domain_controller

    def set_domain_controllers(self, args):
        pass
    
    def get_primary_domain_controllers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        primary_domain_controllers = self.adc.get_primary_domain_controllers(
            domain, site)
        for primary_domain_controller in primary_domain_controllers:
            print >> sys.stdout, primary_domain_controller

    def set_primary_domain_controllers(self, args):
        pass
    
    def get_global_catalog_servers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        global_catalog_servers = self.adc.get_global_catalog_servers(
            domain, site)
        for global_catalog_server in global_catalog_servers:
            print >> sys.stdout, global_catalog_server

    def set_global_catalog_servers(self, args):
        pass
    
    def get_forest_global_catalog_servers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        forest_global_catalog_servers = \
            self.adc.get_forest_global_catalog_servers(domain, site)
        for forest_global_catalog_server in forest_global_catalog_servers:
            print >> sys.stdout, forest_global_catalog_server

    def set_forest_global_catalog_servers(self, args):
        pass
    
    def get_kerberos_servers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        kerberos_servers = self.adc.get_kerberos_servers(domain, site)
        for kerberos_server in kerberos_servers:
            print >> sys.stdout, kerberos_server

    def set_kerberos_servers(self, args):
        pass
    
    def get_kerberos_domain_controllers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        kerberos_domain_controllers = \
            self.adc.get_kerberos_domain_controllers(domain, site)
        for kerberos_domain_controller in kerberos_domain_controllers:
            print >> sys.stdout, kerberos_domain_controller

    def set_kerberos_domain_controllers(self, args):
        pass
    
    def get_kpasswd_servers(self, args):
        domain, site = self.domain_site_parse(args)
        if not domain:
            domain = self.adc.domainname 

        kpasswd_servers = self.adc.get_kpasswd_servers(domain, site)
        for kpasswd_server in kpasswd_servers:
            print >> sys.stdout, kpasswd_server

    def set_kpasswd_servers(self, args):
        pass


def main():
    adts = ADToolShell()

    if len(sys.argv) == 1:
        adts.cmdloop()

    try:
        adts.onecmd(string.join(sys.argv[1:], ' '))

    except Exception as e:
        ret = 1

    sys.exit(0)

if __name__ == '__main__':
    main()
