from org.apache.tools.ant import Task
from org.apache.tools.ant.types import ZipFileSet
from org.apache.tools.ant.taskdefs import War
from java.io import File

import os
from imp import load_source
import sys
import pickle
import tempfile
import shutil
import zipfile
from xml.dom import minidom

from com.orangescape.entity.HibernateMappingGenerator import printMapping
from orangescape.model.server.db.MappingGenerator import ApplicationMappingGenerator

from orangescape.log.logging import getLogger

__logger = getLogger('Deployer.py')

class Deploy(Task):

    application_path=None
    application_name=None
    application_id=None
    deploy_path=None
    temp_dir=None
    appWarPath=None
    appWarFile=None

    def execute(self,tempDir,deploy_path,app_path):
        self.application_path=os.path.abspath(app_path)
        self.deploy_path=deploy_path
        self.temp_dir=tempDir
        __logger.info('generating database mapping files..')
        self.__generateMapping__()
        __logger.info('creating WAR Archive..')
        self.__bundleWAR__()
#        cmd='%GLASSFISH_HOME%/bin/asadmin.bat deploy --force=true --port 6714 --user admin --password adminadmin '+self.deploy_path+'\\'+self.application_id+'.war'
#        __logger.info('deploying application \''+self.application_name+'\'..')
#        os.system(cmd)

    def __generateMapping__(self):
        abspath=os.path.join(self.application_path,"application","pckapp")
        app_file=open(os.path.join(abspath,'Application.pck'),'rb')
        app_metadata=pickle.load(app_file)
        app_file.close()
        self.application_name=app_metadata[app_metadata['root']]['SheetName']
        self.application_id=app_metadata[app_metadata['root']]['SheetId']
        adminWarPath=os.path.join(deploy_path,'orangescape.war')
        self.appWarPath=os.path.join(deploy_path,self.application_id+'.war')
        shutil.copy(adminWarPath,self.appWarPath)
        self.appWarFile=zipfile.ZipFile(self.appWarPath,'a')
        self.appWarFile.write(os.path.join(abspath,'Application.pck'),os.path.join('wsgiapp','orangescape','application','Application.pck'))
        metaMap = dict()
        for sheetId in app_metadata[app_metadata['root']]['Application.SheetMetadata']:
            sheet_file=open(os.path.join(abspath,sheetId+'.pck'),'rb')
            sheet_metadata=pickle.load(sheet_file)
            sheet_file.close()
            self.appWarFile.write(os.path.join(abspath,sheetId+'.pck'),os.path.join('wsgiapp','orangescape','application',sheetId+'.pck'))
            metaMap[sheetId]=sheet_metadata
        self.appWarFile.write(os.path.join(abspath,'formmapping.pck'),os.path.join('wsgiapp','orangescape','application','formmapping.pck'))
        self.appWarFile.write(os.path.join(abspath,'actionmapping.pck'),os.path.join('wsgiapp','orangescape','application','actionmapping.pck'))
        self.appWarFile.write(os.path.join(abspath,'importmapping.pck'),os.path.join('wsgiapp','orangescape','application','importmapping.pck'))
        index_file=open(os.path.join(abspath,'rdbms_indexes.pck'),'rb')
        indexes=pickle.load(index_file)
        index_file.close()
        g=ApplicationMappingGenerator(app_metadata)
        g.generateMapping(metaMap,indexes)
        g.writeMappings(printMapping,os.path.abspath(self.temp_dir))

    def __bundleWAR__(self):
        appCtxSrcPath=os.path.join(deploy_path,'orangescape','WEB-INF','applicationContextTemplate.xml')
        doc=minidom.parse(appCtxSrcPath)
        mapping_list_element=doc.getElementsByTagName('list')[0]
        for root, dirs, files in os.walk(self.temp_dir):
            for mapping_file in files:
                 if not mapping_file=='applicationContext.xml':
                    self.appWarFile.write(os.path.join(os.path.abspath(self.temp_dir),mapping_file), os.path.join('WEB-INF','classes',mapping_file))
                    mapping_file_value = doc.createElement('value')
                    mapping_file_value.appendChild(doc.createTextNode(mapping_file))
                    mapping_list_element.appendChild(mapping_file_value)
        self.createHibernateConfigJNDIinAppContextXML(doc)
        appCtxDestPath = os.path.join(os.path.abspath(self.temp_dir),'applicationContext.xml')
        appCtxDestFile = open(appCtxDestPath,'w')
        appCtxDestFile.write(doc.toxml())
        appCtxDestFile.close()
        self.appWarFile.write(appCtxDestPath,os.path.join('WEB-INF','applicationContext.xml'))
        config = self.appWarFile.read('resources/appconfig.py')
        base_url='\nBASE_PRIMARY_URL=\'/'+self.application_id+'/1\''
        configFile=open(os.path.join(self.temp_dir,'appconfig.py'),'w')
        configFile.write(config+base_url)
        configFile.close()
        self.appWarFile.write(os.path.join(self.temp_dir,'appconfig.py'),os.path.join('wsgiapp','appconfig.py'))
        self.__addFromDir__(os.path.abspath(self.temp_dir),self.appWarFile)
        from MigrationTasks import addTextTagtoJstl
        addTextTagtoJstl(os.path.join(self.application_path,"static","jstl"), self.application_id)
        self.__addFromDir__(os.path.join(self.application_path,"static"),self.appWarFile,'static')
        """ Ehcache configuration """
        self.configEhcache()
        self.appWarFile.close()

    def __addFromDir__(self,dirPath,appWarFile,prefix=''):
        root_len = len(os.path.abspath(dirPath))
        for root, dirs, files in os.walk(dirPath):
            archive_root = prefix+os.path.abspath(root)[root_len:]
            for f in files:
                if not f.count('mapping.xml')>0:
                    fullpath = os.path.join(root, f)
                    archive_name = os.path.join(archive_root, f)
                    appWarFile.write(fullpath, archive_name, zipfile.ZIP_DEFLATED)
        return appWarFile

    def createHibernateConfigJNDIinAppContextXML(self,xmldoc):
        for beanElement in xmldoc.getElementsByTagName('bean'):
            id = beanElement.getAttribute("id")
            if id and id=="HibernateConfiguration":
                for propElement in beanElement.getElementsByTagName("prop"):
                    key = propElement.getAttribute("key")
                    if key and key=="hibernate.connection.datasource":
                        propElement.appendChild(xmldoc.createTextNode("jdbc/%s"%self.application_id))
                        return

    def configEhcache(self):
        ehcacheXMLFile=open(os.path.join(deploy_path,'orangescape','resources','ehcache.xml'))
        xmldoc=minidom.parse(ehcacheXMLFile)
        ehcacheXMLFile.close()
        cacheElements=xmldoc.getElementsByTagName('cache')
        for cacheElement in cacheElements:
            if cacheElement.getAttribute("name"):
                cacheElement.setAttribute("name",self.application_id)
                break
        cacheElements=xmldoc.getElementsByTagName('cacheManagerPeerListenerFactory')
        properties="hostName=, port="+port+", socketTimeoutMillis="+skt_timeout
        for cacheElement in cacheElements:
            if cacheElement.getAttribute("properties"):
                cacheElement.setAttribute("properties",properties)
                break

        cacheElements=xmldoc.getElementsByTagName('cacheManagerPeerProviderFactory')
        properties="peerDiscovery=automatic, multicastGroupAddress="+mcast_grpAdr+", multicastGroupPort="+mcast_grpPrt+", timeToLive=32"
        for cacheElement in cacheElements:
            if cacheElement.getAttribute("properties"):
                cacheElement.setAttribute("properties",properties)
                break
        self.appWarFile.writestr('WEB-INF/classes/ehcache.xml',xmldoc.toprettyxml(indent="  ",newl=""))

if not len(sys.argv) > 2:
    print sys.argv[0]
    print sys.argv[1]
    __logger.error('Path to application files not specified! Exiting deployment!')
else:
    app_path=sys.argv[1]
    deploy_path=sys.argv[2]
    if not len(sys.argv) > 6:
        mcast_grpAdr = "230.0.0.1"
        mcast_grpPrt = "4446"
        port = "40000"
        skt_timeout="2000"
    else:
        mcast_grpAdr=sys.argv[3]
        mcast_grpPrt=sys.argv[4]
        port=sys.argv[5]
        skt_timeout=sys.argv[6]
    tempDir = tempfile.mkdtemp()
    deployer=Deploy()
    deployer.execute(tempDir,os.path.normpath(deploy_path),os.path.normpath(app_path))
