#!/usr/bin/env python

""" Python class to upload nciso xml information into a csw catalog """

__author__ = "Joan Sala Calero"
__version__ = "0.1"
__email__ = "joan.salacalero@deltares.nl"
__status__ = "Prototype"

import os
import logging
import requests
from owslib.csw import CatalogueServiceWeb
from owslib.ows import ExceptionReport
from lxml.etree import XMLSyntaxError
from GMI2GMD import gmi2gmd


class cswUpload:
    # Class init, gmd namespace and input file
    def __init__(self, geonetwork_in, url_logo_in, indir):
        # Default logo
        self.url_logo = url_logo_in
        # Geonetwork instance
        self.geonetwork = geonetwork_in
        # Directory tree
        self.iso_dir = indir

        # Add information of the Geonetwork instance
        self.gn_url = geonetwork_in['host']
        self.gn_user = geonetwork_in['user']
        self.gn_pass = geonetwork_in['pass']
        self.gn_login_j = self.gn_url + '/j_spring_security_check'
        self.gn_logout_j = self.gn_url + '/j_spring_security_logout'
        self.gn_insert_url = self.gn_url + '/srv/eng/csw-publication'

    def geonetwork_login(self):
        """
        Login Geonetwork. Session is used to push metadata
        """
        session = requests.Session()
        params = {'username': self.gn_user, 'password': self.gn_pass}
        response_login = session.post(self.gn_login_j, data=params)

        if response_login.status_code != 200: logging.info('Login to geonetwork failed')

        return session

    # Look for files to push to CSW server
    def getfiles2push(self, dir, files2push):
        # ISo files (xml)
        files = [f for f in os.listdir(dir) if f.endswith('.xml')]

        # Small directory (all files will be pushed)
        if len(files) < 11:
            for f in files:
                files2push.append(os.path.join(dir, f))

        # Big directory (only one of the files will be uploaded, probably timesteps per nc)
        else:
            # Get a sample timestep (from the middle)
            files2push.append(os.path.join(dir, files[10]))

    # Upload xml file to CSW instance
    def push2csw(self):
        # Recursive TDS iso xml tree
        files2push = []
        for root, directories, filenames in os.walk(self.iso_dir):
            for f in filenames:
                files2push.append(os.path.join(root, f))
            for d in directories:
                self.getfiles2push(os.path.join(root, d), files2push)

        # Push the selected files
        for isoxml in files2push:
            self.upload_csw_iso(isoxml)

    # Format adaptation and upload to CSW server
    def upload_csw_iso(self, infile):
        global namespaces_gmd
        try:
            # Convert from GMI iso to GMD metadata
            c = gmi2gmd(self.url_logo)
            xmlcontent = c.convert(infile)

            xml_insert = '''<?xml version="1.0" encoding="UTF-8"?>
                <csw:Transaction service="CSW" version="2.0.2" xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">
                   <csw:Insert>
                   {0}
                   </csw:Insert>
                </csw:Transaction>'''.format(xmlcontent)

            session = self.geonetwork_login()
            headers = {'Content-Type': 'application/xml'}

            # Insert metadata (POST request)
            response_insert = session.post(
                self.gn_insert_url, data=xml_insert, headers=headers)  # insert metadata

            session.post(url=self.gn_logout_j, headers={
                'Connection': 'close'})  # close your session

            if 200 <= response_insert.status_code < 300:
                logging.info(response_insert.text)
            else:
                logging.info("ERROR status code: %i" % response_insert.status_code)
                error_report_file = os.path.join(os.path.dirname(__file__),
                                                 'error%ireport.html' % response_insert.status_code)
                with open(error_report_file, 'w') as fobj:
                    fobj.write(response_insert.text)

                xml_file = os.path.join(os.path.dirname(__file__), 'error%i.xml' % response_insert.status_code)
                with open(xml_file, 'w') as fobj:
                    fobj.write(xmlcontent)

            logging.info('Uploading [OK] -> ' + infile)
        except ExceptionReport:
            logging.warning('Uploading [EXIST] -> ' + infile)
        except IOError:
            logging.error('Uploading [FILEMISS] -> ' + infile)
        except XMLSyntaxError:
            logging.error('Uploading [XMLERR] -> ' + infile)
        except AttributeError:
            logging.error('Uploading [ATTERR] -> ' + infile)


if __name__ == '__main__':
    # ncWMS godiva viewer
    url_godiva = 'http://localhost:8080/ncWMS-1.2/godiva2.html'

    # GeoNetwork CSW endpoint and credentials
    geonetwork_test = {
        'host': 'http://localhost:8080/geonetwork/srv/eng/csw-publication',
        'user': 'admin',
        'pass': 'admin'
    }

    # Default logo url
    url_logo = 'http://marineproject.openearth.nl/images/logo_OET.png'

    # Unit Test
    t = cswUpload(geonetwork_test, url_logo, url_godiva, './iso')
    t.push2csw()
