'''
Created on Sep 25, 2012

@author: Jose Antonio Sal y Rosas Celi
@contact: arturo.jasyrc@gmail.com
'''

import optparse, os
from datetime import datetime

from lib.systems.foldersAndfiles import Folders

from components.upload.upload import upload
from components.upload.create import create

from apidbcore.administrator import Administrator


class appUpload():
    
    def __init__(self, workpath):
        sop = Folders()
        sop.checkFolder(workpath)
        
        self.minDate = None
        self.maxDate = None
        self.done = True
        self.stop = False
        self.num_ops = 0
        self.num_ended_ops = 0
        self.queue_code = 0

    # Stop operation
    def setStop(self):
        self.stop = True

    # Upload data
    def upload(self, dataList, newParameters, queueData, connection, sendto, flag_subexps):
        # Set default value
        lsSubexps = []
        
        # Get current
        startOp = datetime.today()
        
        op_create = create()
        
        # Set Log
        objLogOp = Administrator()
        objLogOp.set_parameters(newParameters["workpath"])
        objLogOp.setLog(queueData["code"])
        self.queue_code = queueData["code"]
        
        # Get queue_id
        newParameters["queue_id"] = queueData["id"]
        
        # Get queue_code
        newParameters["queue_code"] = queueData["code"]
        
        for element in dataList:
            if not self.stop:
                newParameters["ruta"] = element["path"]
                newParameters["day"] = element["date"]
                if element["subexp"] != 0:
                    newParameters["subexp"] = element["subexp"]
                else:
                    newParameters["subexp"] = ""
                
                # Execute operation
                flag_op_cancel, op_id, op_code, filename, totalTime = op_create.execute(newParameters, connection)
                
                # Check if the operation was cancel
                if flag_op_cancel:
                    self.done = False
                    break
                else:
                    self.num_ended_ops += 1
                    lsSubexps = self.sortSubexps(lsSubexps, element, op_id, op_code, filename, totalTime)
                    self.setPeriod(element["date"])
                    
            else:
                self.done = False
                break
        #end for => register all create operations
        
        if self.done:
            # Set parameters for queue
            dicParameters = {"exp_id": newParameters["experimento"],
                             "inst_id": newParameters["instrumento"],
                             "campaign": newParameters["campaign"],
                             "dt": newParameters["tipodatos"],
                             "sendto": sendto,
                             "min": self.minDate,
                             "max": self.maxDate,
                             "subexps": flag_subexps,
                             }
            
            # Finish upload
            self.endUpload(dicParameters, newParameters["workpath"], connection, queueData, lsSubexps)
            
        else:
            # Cancel upload
            self.cancelUpload(queueData["id"])

        # Get current time
        end_op = datetime.today()
        
        # Calculate Total Time
        total_time = end_op - startOp
        
        print "\nTime of Operation: %s" % total_time

    # Register Upload
    def register(self, parameters):
        type_queue = 1
        
        op_upload = upload()
        
        # Check parameters
        op_upload.checkParameters(parameters)
        
        # Get Data
        dataList = op_upload.getData(parameters["ruta"], parameters["subexps"])
        self.num_ops = len(dataList)
        
        # Set parameters
        newParameters = op_upload.setParameters(parameters)
        
        # Register queue
        queueData, connection = op_upload.register(type_queue)
        
        return dataList, newParameters, queueData, connection

    # Finish Upload
    def endUpload(self, dicParameters, workpath, connection, queueData, lsSubexps):
        op_upload = upload()
        
        # Save file
        file_result, final_path_result = op_upload.saveOp(dicParameters, lsSubexps, queueData["code"], workpath)
        
        # Send result (XML file)
        op_upload.sendFileResult(final_path_result, queueData["path"], connection)
        
        # Update queue
        result_dict = op_upload.update(queueData["id"], file_result)
        
        if result_dict["result"] == 1:
            print "%s.\nOperation enqueque." % result_dict["message"]
        else:
            print result_dict["message"]

    # Cancel Upload
    def cancelUpload(self, queue_id):
        op_upload = upload()
        
        # Delete queue
        result_dict = op_upload.cancel(queue_id)
        
        # Show result
        print result_dict["message"]

    # Organize subexperiments
    def sortSubexps(self, lsSubexps, element, op_id, op_code, filename, totaltime):
        lsData = []
        dicData = {}
        
        dicData["data"] = {"date": element["date"], "op_id": op_id, "op_code": op_code,
                           "filename": filename, "time": totaltime,
                           }
        
        if len(lsSubexps) == 0:
            lsData = [dicData]
            
            dicSubexp = {"subexp": element["subexp"], "min": element["date"],
                         "max": element["date"], "data": lsData,
                         }
            lsSubexps.append(dicSubexp)
        else:
            found = False
            for i, subexp in enumerate(lsSubexps):
                if subexp["subexp"] == element["subexp"]:
                    found = True
                    break
            if found:
                # Set period of detail
                if lsSubexps[i]["min"] > element["date"]:
                    lsSubexps[i]["min"] = element["date"]
                if lsSubexps[i]["max"] < element["date"]:
                    lsSubexps[i]["max"] = element["date"]
                
                lsData = lsSubexps[i]["data"]
                lsData.append(dicData)
                lsSubexps[i]["data"] = lsData
            else:
                lsData = [dicData]
                dicSubexp = {"subexp": element["subexp"], "min": element["date"],
                             "max": element["date"], "data": lsData,
                             }
                lsSubexps.append(dicSubexp)
        
        return lsSubexps

    def setPeriod(self, dateofCampaign):
        if self.minDate == None:
            self.minDate = dateofCampaign
        else:
            if self.minDate > dateofCampaign:
                self.minDate = dateofCampaign
        
        if self.maxDate == None:
            self.maxDate = dateofCampaign
        else:
            if self.maxDate < dateofCampaign:
                self.maxDate = dateofCampaign

    def getNumOps(self):
        return self.num_ops

    def getEndedOps(self):
        return self.num_ended_ops

    def getQueueCode(self):
        return self.queue_code


usage = "SCRIPT LOCAL PARA EL ACCESO A LOS DATOS DE JICAMARCA::::::::::::\n" \
        'UPLOAD NEW CAMPAIGNS:\n' \
        'python appUpload.py -p "path/to/workpath" -s "(site_id)" -e "(exp_id)" -i "(inst_id)" -c "(campaign_name)/(campaign_id)"' \
        '-n "yes/no" -d 1/2/3 -r "path/to/file" -m "metadata.zip" -c "configuracion.zip" -q -u "sendto@email.com"' 
    

if __name__ == '__main__':

        parser = optparse.OptionParser(usage=usage)
        
        parser.add_option("-p", "--path", dest="workpath", type="string", default="", help="Workpath")
        parser.add_option("-s", "--site", dest="site", type="string", help="Site ID")
        parser.add_option("-e", "--experiment", dest="experiment", type="string", help="Experiment's ID")
        parser.add_option("-i", "--instrument", dest="instrumento", type="string", default="", help="Instrument's ID")
        parser.add_option("-c", "--campaign", dest="campaign", default="", help="Experiment's campaign")
        parser.add_option("-n", "--subexps", dest="subexps", default="", help="Subexperiments existence")
        parser.add_option("-d", "--datatype", dest="datatype", type="int", default=1, help="Data type of the experiment")
        parser.add_option("-v", "--detail", dest="detail", action="store_true", default=True, help="Detailed Type of XML result ")
        parser.add_option("-q", "--quiet", dest="detail", action="store_false", default=False, help="Large Type of XML result")
        parser.add_option("-r", "--source", dest="source", type="string", default="", help="Path o file of source files")
        parser.add_option("-m", "--metadata", dest="metadata", default="", help="Metadata de los datos del experimento")
        parser.add_option("-g", "--config", dest="config", default="", help="Experiment's configuration")
        parser.add_option("-u", "--sendto", dest="sendto", type="string", default="", help="Receiver of the notification")
                
        (options, args) = parser.parse_args()
    
        site = options.site
        workpath = options.workpath
        experimento = options.experiment
        instrumento = options.instrumento
        campaign = options.campaign
        subexps = options.subexps
        datatype = options.datatype
        detalleXML = options.detail
        ruta_origen = options.source
        metadata = options.metadata
        configuracion = options.config
        sendto = options.sendto
        
        if workpath == "":
            # Set current path by default
            workpath = os.path.dirname(os.path.abspath(__file__))
        
        # Get OS
        if os.name == "posix":
            so = "L"
        else:
            so = "W"
        
        parameters = {"site": site,
                      "workpath": workpath,
                      "experimento": experimento,
                      "instrumento": instrumento,
                      "campaign": campaign,
                      "tipodatos": datatype,
                      "ruta": ruta_origen,
                      "sistema": so,
                      "metadata": metadata,
                      "conf": configuracion,
                      "subexps": subexps.lower(),
                      "sendto": sendto,
                      }
        
        app = appUpload(workpath)
        dataList, newParameters, queueData, connection = app.register(parameters)
        app.upload(dataList, newParameters, queueData, connection, sendto, parameters["subexps"])
