import os
import subprocess
import stat
import sys

import pathContainers as pc
import applicationConfig as ac

import fileGenerator
import utils

import applicationJsonGenerator


def deployPackage(modulePath, mvnClean=True, skipTests=True, offline=False, skipIncrementalBuild=False, useYaMake=False):
    print "run with settings: mvnClean=" + str(mvnClean) + " skipTests=" + str(skipTests) + " offline=" + str(offline) + \
          " skipIncrementalBuild=" + str(skipIncrementalBuild) + " useYaMake=" + str(useYaMake)
    applicationConfig = utils.createApplicationConfig(modulePath)
    applicationConfig.packagingMode = "deploy"

    applicationDevelopmentJson = applicationConfig.assemblyHelper.path + "/application.development.json"
    if os.path.exists(applicationDevelopmentJson):
        print "Load: {0}".format(applicationDevelopmentJson)
        with open(applicationDevelopmentJson) as applicationDevelopmentJsonFile:
            applicationDevelopmentConfig = ac.ApplicationConfig()
            ac.parseApplicationConfigJson(applicationDevelopmentJsonFile, applicationDevelopmentConfig)
            applicationDevelopmentJsonFile.close()
            applicationConfig = ac.mergeConfigs(applicationConfig, applicationDevelopmentConfig)

    applicationCommonDevelopmentJson = applicationConfig.assemblyHelper.path + "/../application.development.json"
    applicationCommonDevelopmentJson = os.path.abspath(applicationCommonDevelopmentJson)
    if os.path.exists(applicationCommonDevelopmentJson):
        print "Load: {0}".format(applicationCommonDevelopmentJson)
        with open(applicationCommonDevelopmentJson) as applicationDevelopmentJsonFile:
            applicationDevelopmentConfig = ac.ApplicationConfig()
            ac.parseApplicationConfigJson(applicationDevelopmentJsonFile, applicationDevelopmentConfig)
            applicationDevelopmentJsonFile.close()
            applicationConfig = ac.mergeConfigs(applicationConfig, applicationDevelopmentConfig)

    applicationConfig.folderHelper = pc.DevelopmentFolderHelper(applicationConfig)
    ac.resolveProperties(applicationConfig)
    ac.setDefaults(applicationConfig)

    currentWorkingDirectoryCache = os.getcwd()
    os.chdir(applicationConfig.assemblyHelper.path)

    if useYaMake:
        utils.runYaMake(applicationConfig, mvnClean, skipTests)
    else:
        utils.runMaven(applicationConfig, mvnClean, skipTests, offline, skipIncrementalBuild)

    fileGenerator.generateStartScript(applicationConfig)
    utils.copyDeployment(applicationConfig)
    os.chdir(currentWorkingDirectoryCache)
    os.chmod(applicationConfig.assemblyHelper.binFolder + "/start.sh", stat.S_IRWXU | stat.S_IRWXG)
    createDeveopmentScripts(applicationConfig)
    applicationJsonGenerator.generate(applicationConfig.assemblyHelper.binFolder + "/application.json", applicationConfig)
    runDeployment(applicationConfig)


def createDeveopmentScripts(applicationConfig):
    assemblyHelper = applicationConfig.assemblyHelper

    devStartShPath = assemblyHelper.assemblyRoot + "/start.sh"
    devStopShPath = assemblyHelper.assemblyRoot + "/stop.sh"
    devRestartShPath = assemblyHelper.assemblyRoot + "/restart.sh"
    devRShPath = assemblyHelper.assemblyRoot + "/r.sh"

    if os.path.exists(devStartShPath):
        os.remove(devStartShPath)
    if os.path.exists(devStopShPath):
        os.remove(devStopShPath)
    if os.path.exists(devRestartShPath):
        os.remove(devRestartShPath)
    if os.path.exists(devRShPath):
        os.remove(devRShPath)

    fileGenerator.generateDevelopmentScripts(applicationConfig)

    mode = stat.S_IRWXU | stat.S_IRWXG
    os.chmod(devStartShPath, mode)
    os.chmod(devStopShPath, mode)
    os.chmod(devRestartShPath, mode)
    os.chmod(devRShPath, mode)


def runDeployment(applicationConfig):
    if applicationConfig.deploymentConfig:
        assemblyHelper = applicationConfig.assemblyHelper
        devStartShPath = assemblyHelper.assemblyRoot + "/start.sh"
        devStopShPath = assemblyHelper.assemblyRoot + "/stop.sh"
        devRestartShPath = assemblyHelper.assemblyRoot + "/restart.sh"
        devRShPath = assemblyHelper.assemblyRoot + "/r.sh"

        deploymentHost = applicationConfig.deploymentConfig.host
        deploymentPath = applicationConfig.deploymentConfig.getPath(applicationConfig)
        if deploymentHost is None or deploymentPath is None:
            print "Deployment host and path must be specified"
        else:
            print "Deploy to {0}".format(applicationConfig.deploymentConfig.host)
            rsyncFolder(assemblyHelper.libFolder, deploymentHost, deploymentPath)
            rsyncFolders([assemblyHelper.binFolder, assemblyHelper.etcFolder], deploymentHost, deploymentPath, False)

            rsyncFiles([devStartShPath, devStopShPath, devRestartShPath, devRShPath], deploymentHost, deploymentPath + "/")
    else:
        print "Deployment config not found"


def rsyncFolders(srcs, destHost, destPath, cleanFolder=True):
    command = ["rsync", "-rvz"]
    if cleanFolder:
        command.append("--delete")
    for src in srcs:
        command.extend(["--executability", src])
    command.append("{0}:{1}".format(destHost, destPath))
    print " ".join(command)
    shell = False
    if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
        shell = True
    subprocess.check_call(command, shell=shell)

def rsyncFolder(src, destHost, destPath, cleanFolder=True):
    rsyncFolders([src], destHost, destPath, cleanFolder)

def rsyncFiles(srcs, destHost, destPath):
    command = ["rsync", "-vz"]
    for src in srcs:
        command.extend(["--executability", src])
    command.append("{0}:{1}".format(destHost, destPath))
    print " ".join(command)
    shell = False
    if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
        shell = True
    subprocess.check_call(command, shell=shell)


def rsyncFile(src, destHost, destPath):
    rsyncFiles([src], destHost, destPath)


