import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.api import memcache
from google.appengine.ext import db

from orangescape.model.engine.Component import Component
from orangescape.model.server.DataViewer import BaseDataViewer

from cgi import parse_qs
import logging


class Migrate(webapp.RequestHandler, BaseDataViewer):
    def __init__(self):
        BaseDataViewer.__init__(self)

    def clearCache(self):
        logging.info('Clearing memcache')
        memcache.flush_all()

    def updateAppRef(self):
        logging.info('Migration: Update Application Reference in SheetMetadata')
        query_str = self.request.query_string
        querydict=self.getQueryStringParams(query_str)
        if querydict.get("ApplicationId"):
            appId = querydict.get("ApplicationId")
            component = Component(self.session)
            application = self.session.get(appId,self.session.getApplication().getSheetMetadata('Application'))
            sheetMetadata = self.session.getApplication().getSheetMetadata('SheetMetadata')
            sheet_app_refCell = sheetMetadata.getPublicCellMetadata('Application')
            for sheet in self.session.getList(application, sheet_app_refCell):
                logging.info('Updating appref for the sheet %s(%s)'%(sheet.getSheetName(), sheet.getSheetId()))
                modifiedBy = sheet.getValue('ModifiedBy')
                component.update(sheet,{'AppRef':None,'ModifiedBy':modifiedBy})
            self.session.commit()

    def updateAppSubscription(self):
        logging.info('Migration: Update Application Subscribed owner')
        query_str = self.request.query_string
        querydict=self.getQueryStringParams(query_str)
        if querydict.get("ApplicationId"):
            appId = querydict.get("ApplicationId")
            component = Component(self.session)
            application = self.session.get(appId,self.session.getApplication().getSheetMetadata('Application'))
            appSubMetadata = self.session.getApplication().getSheetMetadata('ApplicationSubscription')
            appsub_app_refCell = appSubMetadata.getPublicCellMetadata('Application')
            for sheet in self.session.getList(application, appsub_app_refCell):
                logging.info("The Application Subscribed for the user %s"%sheet.getValue('SubscribedUser'))
                modifiedBy = sheet.getValue('ModifiedBy')
                component.update(sheet,{'SubscribedOwner':'abc','ModifiedBy':modifiedBy})
            self.session.commit()

    def unlockModel(self):
        if self.initUser():
            query_str = self.request.query_string
            querydict=self.getQueryStringParams(query_str)
            if querydict.get("ApplicationId"):
                appId = querydict.get("ApplicationId")
                component = Component(self.session)
                application = self.session.get(appId,self.session.getApplication().getSheetMetadata('Application'))
                sheetMetadata = self.session.getApplication().getSheetMetadata('SheetMetadata')
                if querydict.get("SheetId"):
                    sheetId = querydict.get("SheetId")
                    sheet = self.session.get(sheetId, sheetMetadata)
                    logging.info('Updating ModifiedBy for the sheet %s'%( sheet.getSheetName() ))
                    component.update(sheet,{'ModifiedBy':None})
                else:
                    sheet_app_refCell = sheetMetadata.getPublicCellMetadata('Application')
                    for sheet in self.session.getList(application, sheet_app_refCell):
                        logging.info('Updating ModifiedBy for the sheet %s(%s)'%(sheet.getSheetName(), sheet.getSheetId()))
                        component.update(sheet,{'ModifiedBy':None})
                self.session.commit()

    def getQueryStringParams(self, values):
        params = parse_qs(values, True)
        for key, value in params.iteritems():
                params[key] = value[0]
        return params


    def delete(self):
        if self.initUser():
            component = Component(self.session)
            applicationSubcriptionMetadata = self.application.getSheetMetadata('ApplicationSubscription')
            appSubscriptionList = self.session.advQuery(applicationSubcriptionMetadata, 2000)
            for appSub in appSubscriptionList:
                component.delete(appSub)
            self.session.commit()

    def updateProcess(self):
        if self.initUser():
            component = Component(self.session)
            processMetadata = self.application.getSheetMetadata('ProcessInstance')
            processList = self.session.advQuery(processMetadata, 2000)
            for process in processList:
                if (process.getValue('MetadataName') == 'Application'):
                    component.update(process,{'MetadataName':'My Applications'})
                elif(process.getValue('MetadataName') == 'ParticipatingCompany'):
                    component.update(process,{'MetadataName':'Other Applications'})
                elif (process.getValue('MetadataName') == 'ApplicationSubscription'):
                    component.update(process,{'MetadataName':'Subscribed Applications'})

            self.session.commit()

    def participatingCompany(self):
         if self.initUser():
            component = Component(self.session)
#            applicationSubscriptionMetadata = self.application.getSheetMetadata('ApplicationSubscription')
#            applicationSubscriptionList = self.session.query(applicationSubscriptionMetadata, 2000)
#            for appSub in applicationSubscriptionList:
#                component.update(appSub,{'ApplicationId':'test'})
            participatingCompanyMetadata = self.application.getSheetMetadata('ParticipatingCompany')
            processMetadata = self.application.getSheetMetadata('ProcessInstance')
            participatingCompanyList = self.session.advQuery(participatingCompanyMetadata, 2000)
            for partComp in participatingCompanyList:
                processSheet = self.session.get(partComp.getValue('ProcessInstance'),processMetadata)
                if partComp.getValue('Company') == 'Company_gmail':
                    component.update(partComp,{'AssignedTo':'User_4576a6dc_d9f2_11de_a331_1784184aa93e'})
                    component.update(processSheet,{'InstanceAssignedTo':'User_4576a6dc_d9f2_11de_a331_1784184aa93e'})
                elif partComp.getValue('Company') == 'Company_orangescape':
                    component.update(partComp,{'AssignedTo':'User_dd8324eb_d9e7_11de_b4fe_af811e5b03bf'})
                    component.update(processSheet,{'InstanceAssignedTo':'User_dd8324eb_d9e7_11de_b4fe_af811e5b03bf'})
                elif partComp.getValue('Company') == 'Company_wipro':
                    component.update(partComp,{'AssignedTo':'User_50294940_d9f2_11de_bf9c_1784184aa93e'})
                    component.update(processSheet,{'InstanceAssignedTo':'User_50294940_d9f2_11de_bf9c_1784184aa93e'})
            self.session.commit()

    def getQuery(self):
        if self.initUser():
            component = Component(self.session)
            applicationMetadata = self.application.getSheetMetadata('Application')
            appList = self.session.advQuery(applicationMetadata, 2000)
            branchList = applicationMetadata.getBranchList()
            appendBranch = None
            for branch in branchList:
                if branch.getSheetName() == 'ApplicationApproval':
                    appendBranch = branch
                    break;


            processMetadata = self.application.getSheetMetadata('ProcessInstance')
            for app in appList:
                if(app.getValue('Status') == 'ActivityDefinition_ee1b5268_16ed_4af7_bd6a_4f6fbbb5542b'):
                    self.response.out.write(' <br> '+app.getSheetId()+' *********************************************** '+app.getSheetName())
                    processSheet = self.session.get(app.getValue('ProcessInstance'),processMetadata)
                    component.update(processSheet,{'ActivityName':'My Applications',
                                                   'ActivityDefinition':'ActivityDefinition_5785c8b1_e643_4ca3_9fdf_f03639c949ca',
                                                   'InstanceAssignedTo':app.getValue('CreatedBy')
                                                })
                    component.update(app,{'Status':'ActivityDefinition_5785c8b1_e643_4ca3_9fdf_f03639c949ca',
                                          'AssignedTo':app.getValue('CreatedBy')
                                          })
                    component.executeAction(app,appendBranch)

#            participatingCompanyMetadata = self.application.getSheetMetadata('ParticipatingCompany')
#            participatingCompanyList = self.session.query(participatingCompanyMetadata, 2000)
#            for partComp in participatingCompanyList:
#                self.response.out.write('<br>'+partComp.getSheetId()+' ===== '+partComp.getValue('Status')+' === '+partComp.getValue('ApplicationName')+' ==== '+partComp.getValue('Application_Company'))
#
#            appSubscriptionList = self.session.query(applicationSubcriptionMetadata, 2000)
#            for appSub in appSubscriptionList:
#                self.response.out.write('<br>'+appSub.getSheetId()+' ===== '+appSub.getValue('Status'))
            self.session.commit()

def migrateApplication(component, applicationId):
    session = component.getSession()
    appMetadata = session.getApplication().getSheetMetadata('Application')
    appInstance = session.get(applicationId, appMetadata)
    subscriptionMetadata = session.getApplication().getSheetMetadata('ApplicationSubscription')
    participatingMetadata = session.getApplication().getSheetMetadata('ParticipatingCompany')

    #migrate applicationsubscription
    subRefCell = subscriptionMetadata.getPublicCellMetadata('Application')
    AppSubSheetId = subscriptionMetadata.getSheetId()
    appSubInstList = session.getList(appInstance, subRefCell)
    for instance in appSubInstList:
        migrateInstance(component, instance, AppSubSheetId)

    #migrate applicationsubscription
    parCompRefCell = participatingMetadata.getPublicCellMetadata('Application')
    praticipatingCompanySheetId = participatingMetadata.getSheetId()
    participatingCompList = session.getList(appInstance, parCompRefCell)
    for instance in participatingCompList:
        migrateInstance(component, instance, praticipatingCompanySheetId)

def migrateInstance(component, instance, sheetId):
    session = component.getSession()
    sheet = instance.getSheetMetadata()
    usrMetadata = session.getApplication().getSheetMetadata('User')
    processInstanceMetadata = session.getApplication().getSheetMetadata('ProcessInstance')
    for cell in sheet.getManyToOneList():
        cellName = cell.getCellName()
        if cellName.endswith('ProcessInstance'):
            assignedToCellName = cellName.replace('ProcessInstance', 'AssignedTo')
            if instance.getValue(cellName) and instance.getValue(assignedToCellName):
                userId = instance.getValue(assignedToCellName)
                user = session.get(userId, usrMetadata)
                userName = user.getValue('UserId').split('@')[0]
                tenant = user.getValue('Company')
                if instance.getValue('Tenant') is None:
                    component.update(instance,{assignedToCellName : userName, 'Tenant': tenant})

                processinstance = session.get(instance.get(cell), processInstanceMetadata)
                if processinstance.getValue('Tenant') is None:
                    component.update(processinstance, {'InstanceAssignedTo':userName, 'InstanceMetadata':'M_'+sheetId, 'Tenant':tenant})

