#!/usr/bin/python
# coding: utf8

# Copyright (C) 2017  Paolo Patruno <p.patruno@iperbole.bologna.it>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#
# Authors: Paolo Patruno <p.patruno@iperbole.bologna.it>

import subprocess
import tempfile
import sys,os,shutil,pwd, errno
import logging
import argparse
import datetime

_version=1.0

default_date = (datetime.datetime.utcnow()-datetime.timedelta(days=7)).strftime("%Y-%m-%d")


parser = argparse.ArgumentParser(description='Migrate data from dballe to arkimet.')
parser.add_argument('--version', action='version',
                    version='%(prog)s {version}'.format(version=_version))
parser.add_argument('-a', '--arkiconf', dest='arkiconf', action='store',
                    default="/rmap/arkimet/arkimet.conf",
                    help='arkiserver to contact. Default: %(default)s')
parser.add_argument('-d', '--dsn', dest='dsn', action='store',
                    default="mysql:///rmap?user=rmap&password=rmap",
                    help='arkiserver to contact. Default: %(default)s')
parser.add_argument('-o', '--outputdir', dest='outputdir', action='store',
                    default="/tmp/"+"/dballe2arkimet",
                    help='output directory where to write data. Default: %(default)s')
parser.add_argument('-f', '--file', dest='outputfile', action='store',
                    default="dballe2arkimet.dat",
                    help='output file name for data. Default: %(default)s')
parser.add_argument('-e', '--date', dest='date', action='store',
                    default=default_date,
                    help='reference date (AAAA-MM-DD). Default: <today-7days>')
#parser.add_argument('-t', '--time', dest='time', action='store',
#                    default="00:00:00",
#                    help='reference time (HH:MM:SS). Default: %(default)s')
parser.add_argument('-p', '--tempprefix', dest='tempprefix', action='store',
                    default="/tmp/",
                    help='Prefix for temporary work directory. Default: %(default)s')
parser.add_argument("--cachedir", metavar="dir", action="store",type=str, default=None,
                    help="cache directory for warped channels. Default: %(default)s")
parser.add_argument("-v","--verbose", action="store",type=bool,default=False,
                    help="set verbosity level to DEBUG, Default: %(default)s")


opts = parser.parse_args()

date=datetime.date(*[int(e) for e in opts.date.split("-")])

def dballe2arkimet(date):


    logging.info("Start to migrate data to arkimet")

    p1=subprocess.Popen (("dbadb", "export", "--dsn", opts.dsn, "yearmax=%s"%date.year,  "monthmax=%s"%date.month , "daymax=%s"%date.day )
                           ,stdout=subprocess.PIPE, stderr=stderr,env={"TMPDIR":opts.cachedir})
    p2=subprocess.Popen (("arki-scan", "--dispatch="+opts.arkiconf , "bufr:-",  "--summary", "--dump", "--status"), stdin=p1.stdout, stdout=subprocess.PIPE,stderr=stderr)
    p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
    st=p2.communicate()
    stdout.write(st[0])
    #stderr.write(st[1])

    logging.info("End to migrate data to arkimet")

    p1.wait()
    logging.info("Return status: %s %s" % (p1.returncode,p2.returncode))
    
    if (p1.returncode == 0 and (p2.returncode==0 or p2.returncode==2)):
        logging.info("Start to delete data from dballe")
        subprocess.check_call (("dbadb", "delete", "--dsn", opts.dsn,  "yearmax=%s"%date.year,  "monthmax=%s"%date.month , "daymax=%s"%date.day )
                               ,stderr=stderr,stdout=stdout,env={"TMPDIR":opts.cachedir})
        logging.info("End to delete data from dballe")
    else:
        logging.error("Error migrate data from dballe to arkimet")
        logging.warning("Do not delete data from dballe")


# Get an instance of a logger

# we want work like fortran ? TODO
#  call getenv("LOG4_APPLICATION_NAME",LOG4_APPLICATION_NAME)
#  call getenv("LOG4_APPLICATION_ID",LOG4_APPLICATION_ID)

if opts.verbose:
    logging.basicConfig(level=logging.DEBUG)
else:
    logging.basicConfig(level=logging.INFO)


logger = logging.getLogger(__name__)

stderr=sys.stderr
stdout=sys.stdout



class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class TmpDirError(Error):
    """Exception raised setting temporary working dir.

    Attributes:
        expr -- input expression in which the error occurred
        msg  -- explanation of the error
    """

    def __init__(self, expr, msg):
        self.expr = expr
        self.msg = msg

    def __str__(self):
        return repr(self.msg)+"Dir: "+repr(self.expr)


class makeenv(object):
    
    def __init__(self,tempprefix=None):

        self.cwd=None

        if tempprefix is not None:
            #tempfile.tempdir=tempprefix
            tmp=tempfile.mkdtemp(prefix=tempprefix)
        else:
            tmp=tempfile.mkdtemp(prefix="/tmp/")

        logging.info("Working temporary directory: "+tmp)
        os.chdir(tmp)

        if not os.path.samefile( tmp, os.getcwd()):
            raise TmpDirError((tmp,os.getcwd()),"Error testing cwd after chdir in tmp working dir")
        else:
            self.cwd=tmp

        # prepare output directory
        try:
            os.makedirs(opts.outputdir)
        except OSError as exc: # Python >2.5
            if exc.errno == errno.EEXIST and os.path.isdir(opts.outputdir):
                pass
            else: raise


    def delete (self):
        
        dangerouspaths=("/","/home","/home/")

        if self.cwd is not None and self.cwd not in dangerouspaths:
            #print "remove working tree ",self.cwd
            shutil.rmtree(self.cwd)
        else:
            logging.info("tempprefix is a dangerous path: do not remove temporary working directoy")



def main():

    logger.info( "start" )
    try:
        logger.info( "makeenv" )
        env=makeenv(tempprefix=opts.tempprefix)
    except TmpDirError as e:
        logger.exception( e )
        raise
    except:
        logger.exception( "premature end" )
        raise

    if opts.cachedir is None:
        opts.cachedir = env.cwd

    try:
        logger.info( "start dballe2arkimet" )
        dballe2arkimet(date)

    except :
        logger.exception("Error happen" )
        raise
    finally:
        env.delete()
        logger.info( "end" )

if __name__ == '__main__':

        stdout.write(sys.argv[0]+" started with pid %d\n" % os.getpid())
        stdout.write(sys.argv[0]+" stdout output\n")
        stderr.write(sys.argv[0]+" stderr output\n")

        # (this code was run as script)
        sys.exit(main())
