#!/usr/bin/env python
# -*- coding: utf-8
"""
@module  db.csw.admin
@brief   Module for creating metadata based on ISO for vector maps

(C) 2015 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.

@author Matej Krejci <matejkrejci gmail.com> (GSoC 2015)
used and modified original pycsw-admin.py from pycsw lib(
https://github.com/geopython/pycsw/blob/master/bin/pycsw-admin.py)
"""


#%module
#% description: CSW database manager
#% keyword: csw
#% keyword: metadata
#%end

#%option G_OPT_F_INPUT
#% key: configure
#% description: path to configure file (default.cfg)
#% required : yes
#% answer : /var/www/html/pycsw/default.cfg
#%end

#%option
#% key: load_records
#% label: Load metadata(folder)
#% description: Loads metadata records from directory into repository
#% guisection: Records
#%end

#%flag
#% key: r
#% label: Load records recursively
#% description: Load records from directory recursively
#% guisection: Records
#%end

#%flag
#% key: s
#% label: Setup database
#% description: Creates repository tables and indexes
#% guisection: Commands
#%end

#%option
#% key: export_records
#% label: Create db dump(folder)
#% description: Dump metadata records from repository into directory
#% guisection: Commands
#%end

#%flag
#% key: i
#% label: Database indexes
#% description: Rebuild repository database indexes
#% guisection: Commands
#%end

#%flag
#% key: o
#% label: Optimize db
#% description: Optimize repository database
#% guisection: Commands
#%end

#%flag
#% key: h
#% label: Refresh harvested records
#% description: Optimize repository database
#% guisection: Commands
#%end

#%option G_OPT_F_OUTPUT
#% key: gen_sitemap
#% label: Sitemap
#% description: Generate XML Sitemap
#% guisection: Commands
#% required: NO
#%end

#%flag
#% key: d
#% label: Delete all records(!!)
#% description: Delete all records without prompting
#% guisection: Commands
#%end

#%flag
#% key: f
#% label: Force confirmation
#% description: Force confirmation of task
#% guisection: Commands
#%end

#%option
#% key: url_csw
#% label: Url of CSW
#% description: Execute a CSW request via HTTP POST: URL of CSW
#% guisection: Execute request
#%end

#%option G_OPT_F_INPUT
#% key: file_xml
#% label: XML file
#% description: Execute a CSW request via HTTP POST: XML FILE
#% guisection: Execute request
#% required: NO
#%end


import sys
import os
import ConfigParser
import getopt

from grass.script import core as grass
from grass.pygrass.utils import set_path

set_path(modulename='wx.metadata', dirname='mdlib')

from mdlib.cswutil import *

try:
    from pycsw.core import admin, config

except:
    sys.exit(
        'pycsw library is missing. Check requirements on the manual page < https://grasswiki.osgeo.org/wiki/ISO/INSPIRE_Metadata_Support >')


class CswAdmin():
    def __init__(self):
        self.COMMAND = None
        self.XML_DIRPATH = None
        self.CFG = None
        self.RECURSIVE = False
        self.OUTPUT_FILE = None
        self.CSW_URL = None
        self.XML = None
        self.XSD = None
        self.TIMEOUT = 30
        self.FORCE_CONFIRM = False
        self.METADATA = None
        self.DATABASE = None
        self.URL = None
        self.HOME = None
        self.TABLE = None
        self.CONTEXT = config.StaticContext()


    def argParser(self, defaultConf, load_records,
                  loadRecurs, setupDB,
                  exportRecord, indexes,
                  optimize, harvest,
                  siteOut, deleteAll,
                  cswURL, cswXML, force):
        if defaultConf is None:
            grass.error('Configure file is not exist')
        args = []
        args.append('-c')

        if load_records:
            args.append('load_records')
            args.append('-p')
            args.append(load_records)
            if loadRecurs:
                args.append('-r')
            if force:
                args.append('y')
            return args

        if setupDB:
            args.append('setup_db')
            args.append('-f')
            args.append(defaultConf)
            return args

        if exportRecord:
            args.append('export_records')
            args.append('-p')
            args.append(exportRecord)
            args.append('-f')
            args.append(defaultConf)
            return args

        if indexes:
            args.append('rebuild_db_indexes')
            args.append('-f')
            args.append(defaultConf)
            return args

        if optimize:
            args.append('optimize_db')
            args.append('-f')
            args.append(defaultConf)
            return args

        if harvest:
            args.append('refresh_harvested_records')
            args.append('-f')
            args.append(defaultConf)
            return args

        if siteOut:
            args.append('gen_sitemaps')
            args.append('-o')
            args.append(siteOut)
            args.append('-f')
            args.append(defaultConf)
            return args

        if deleteAll:
            args.append('delete_records')
            args.append('-f')
            args.append(defaultConf)
            if force:
                args.append('y')
            return args

        if cswURL and cswXML:
            args.append('post_xml')
            args.append('-u')
            args.append(cswURL)
            args.append('-x')
            args.append(cswXML)
            args.append('-f')
            args.append(defaultConf)
            return args

        return False


    def run(self, argv):

        if len(argv) == 0:
            grass.error('Nothing to do. Set args')
            return
        print argv
        try:
            OPTS, ARGS = getopt.getopt(argv, 'c:f:ho:p:ru:x:s:t:y')
        except getopt.GetoptError as err:
            grass.error('\nERROR: %s' % err)
            #print usage()

        for o, a in OPTS:
            if o == '-c':
                self.COMMAND = a
            if o == '-f':
                self.CFG = a
            if o == '-o':
                self.OUTPUT_FILE = a
            if o == '-p':
                self.XML_DIRPATH = a
            if o == '-r':
                self.RECURSIVE = True
            if o == '-u':
                self.CSW_URL = a
            if o == '-x':
                self.XML = a
            if o == '-t':
                self.TIMEOUT = int(a)
            if o == '-y':
                self.FORCE_CONFIRM = True

        if self.CFG is None and self.COMMAND not in ['post_xml']:
            print 'ERROR: -f <cfg> is a required argument'

        if self.COMMAND not in ['post_xml']:
            SCP = ConfigParser.SafeConfigParser()
            SCP.readfp(open(self.CFG))

            self.DATABASE = SCP.get('repository', 'database')
            self.URL = SCP.get('server', 'url')
            self.HOME = SCP.get('server', 'home')
            self.METADATA = dict(SCP.items('metadata:main'))
            try:
                self.TABLE = SCP.get('repository', 'table')
            except ConfigParser.NoOptionError:
                self.TABLE = 'records'

        if self.COMMAND == 'setup_db':
            try:
                admin.setup_db(self.DATABASE, self.TABLE, self.HOME)
            except Exception as err:
                print err
                print 'ERROR: DB creation error.  Database tables already exist'
                print 'Delete tables or database to reinitialize'

        elif self.COMMAND == 'load_records':
            admin.load_records(self.CONTEXT, self.DATABASE, self.TABLE, self.XML_DIRPATH, self.RECURSIVE,
                               self.FORCE_CONFIRM)
        elif self.COMMAND == 'export_records':
            admin.export_records(self.CONTEXT, self.DATABASE, self.TABLE, self.XML_DIRPATH)
        elif self.COMMAND == 'rebuild_db_indexes':
            admin.rebuild_db_indexes(self.DATABASE, self.TABLE)
        elif self.COMMAND == 'optimize_db':
            admin.optimize_db(self.CONTEXT, self.DATABASE, self.TABLE)
        elif self.COMMAND == 'refresh_harvested_records':
            admin.refresh_harvested_records(self.CONTEXT, self.DATABASE, self.TABLE, self.URL)
        elif self.COMMAND == 'gen_sitemap':
            admin.gen_sitemap(self.CONTEXT, self.DATABASE, self.TABLE, self.URL, self.OUTPUT_FILE)
        elif self.COMMAND == 'post_xml':
            grass.message(admin.post_xml(self.CSW_URL, self.XML, self.TIMEOUT))

        elif self.COMMAND == 'delete_records':
            admin.delete_records(self.CONTEXT, self.DATABASE, self.TABLE)


'''#TODO
    def initDatabase(self):
        driverDB = Module('db.connect',
                          flags='pg',
                          quiet=True,
                          stdout_=PIPE)
        self.database = parse_key_val(driverDB.outputs.stdout, sep=': ')
        conf = 'default.cfg'
        modif = os.path.join(os.getenv('GRASS_ADDON_BASE') ,'wx.metadata','etc','config','default.cfg')
        defaultConf = os.path.join(os.getenv('GRASS_ADDON_BASE'),'wx.metadata' ,'etc','config','default-sample.cfg')
        print self.database

        SCP = ConfigParser.SafeConfigParser()
        try:
            SCP.readfp(open(conf))
        except:
            shutil.copy2(defaultConf, conf)
            SCP.readfp(open(conf))

        DATABASE = SCP.get('repository', 'database')
        #URL = SCP.get('server', 'url')
        HOME = SCP.get('server', 'home')


        #currPython=os.path.dirname(os.path.realpath(__file__))
        if not os.path.isdir(HOME):
            grass.message('Cannot find server home folder < %s >' % HOME)
            grass.error('Move pycsw(install foder) to <%s> or set server.home in <default.cfg >'%HOME)

        if not os.access(defaultConf, os.W_OK):
            try:
                shutil.copy2(defaultConf, HOME)
                grass.message('Configure file created in < %s/default.cfg >' % HOME)
            except:
                grass.error('Cannot duplicate <default-sample.cfg> to <default.cfg> ' )
                return

        if not os.access(defaultConf, os.W_OK):
            grass.error('Cannot acces configure file < %s >' % defaultConf)
            return

        if self.database['driver'] == 'sqlite':
            if not os.access(DATABASE, os.W_OK):
                grass.error('Cannot acces databaase < %s >'%DATABASE)
'''
'''
#%flag
#% key: a
#% label: Automatic configuration
#% description: Set database according GRASS default and confugure server
#% guisection: Auto Config
#%end
'''


def main():
    defaultConf = options['configure']
    load_records = options['load_records']
    loadRecurs = flags['r']
    setupDB = flags['s']
    exportRecord = options['export_records']
    indexes = flags['i']
    optimize = flags['o']
    harvest = flags['h']
    siteOut = options['gen_sitemap']
    deleteAll = flags['d']
    cswURL = options['url_csw']
    cswXML = options['file_xml']
    force = flags['f']

    csw = CswAdmin()
    #if flags['a']:
    #csw.initDatabase()
    args = csw.argParser(defaultConf,
                         load_records,
                         loadRecurs,
                         setupDB,
                         exportRecord,
                         indexes,
                         optimize,
                         harvest,
                         siteOut,
                         deleteAll,
                         cswURL,
                         cswXML,
                         force)
    if args:
        csw.run(args)


if __name__ == "__main__":
    options, flags = grass.parser()
    main()
