#!/usr/bin/env py
import os
import os.path
import sys
sys.path.append(os.getenv('HELIX_WORK_ROOT'))
import copy
"""
 This is a temporary solution to gather h/w info from machine
 the package is installed on end machines running perf
 However this runs on a limited number of platforms
 (but supports all the flavors we currently use for testing)
 moving forward we will need a truly cross-plat solution here
"""
from cpuinfo import cpuinfo
import json
import re
import shutil
import socket
import subprocess
import urllib
import urlparse
import helix.azure_storage
import helix.depcheck
import helix.event
import helix.logs
import helix.saferequests
import platform
import psutil
import xunit
import zip_script
from helix.cmdline import command_main
from helix.io import copy_tree_to, ensure_directory_exists, fix_path

log = helix.logs.get_logger()

def _write_output_path(file_path, settings):
    (scheme,_,path,_,_,_) = urlparse.urlparse(settings.output_uri, 'file')
    if scheme.lower() == 'file':
        path = urllib.url2pathname(path)
        output_path = os.path.join(path, os.path.basename(file_path))
        shutil.copy2(file_path, output_path)
        return output_path
    else:
        try:
            fc = helix.azure_storage.get_upload_client(settings)
            url = fc.upload(file_path, os.path.basename(file_path))
            return url
        except ValueError, e:
            event_client = helix.event.create_from_uri(settings.event_uri)
            event_client.error(settings, "FailedUpload", "Failed to upload " + file_path + "after retry", None)

def _prepare_execution_environment(settings, framework_in_tpa, assembly_list_name):
    workitem_dir = fix_path(settings.workitem_working_dir)
    correlation_dir = fix_path(settings.correlation_payload_dir)

    xunit_drop = os.path.join(correlation_dir, 'xunit')
    corerun_drop = os.path.join(correlation_dir, 'corerun')
    build_drop = os.path.join(correlation_dir)

    test_drop = os.path.join(workitem_dir)

    assembly_list = os.path.join(test_drop, assembly_list_name)

    test_location = os.path.join(workitem_dir, 'execution')
    core_root = os.path.join(workitem_dir, 'core_root')

    ensure_directory_exists(test_location)
    ensure_directory_exists(core_root)

    log.info("Copying only test files from {} to {}".format(test_drop, test_location))
    copy_tree_to(test_drop, test_location)

    framework_target = core_root if framework_in_tpa else test_location
    log.info("Copying product binaries from {} to {}".format(build_drop, framework_target))
    _copy_package_files(assembly_list, build_drop, framework_target, core_root, test_location)

def _copy_files_to_dest(src, dest):
    for item in os.listdir(src):
        s = os.path.join(src, item)
        d = os.path.join(dest, item)
        if os.path.isfile(s):
            shutil.copy2(s, d)

def _prepare_linux_env_for_perf(correlation_dir, xunit_perf_drop, test_location, core_root):
    # copy over the cli runner and its dependencies for execution
    _copy_files_to_dest(xunit_perf_drop, test_location)
    xunit_perf_deps = os.path.join(correlation_dir, "Microsoft.DotNet.xunit.performance.run.core")
    if len(os.listdir(xunit_perf_deps)) > 1:
        log.info('Multiple directories found under '+xunit_perf_deps+' picking '+os.listdir(xunit_perf_deps)[0])
    xunit_perf_deps = os.path.join(xunit_perf_deps, os.listdir(xunit_perf_deps)[0])
    xunit_perf_deps = os.path.join(xunit_perf_deps, "lib", "dotnet")
    log.info('Copying xunit perf dependencies from '+xunit_perf_deps)
    _copy_files_to_dest(xunit_perf_deps, test_location)

    dotnet_cli_dir = os.path.join(correlation_dir, "dotnet_cli")

    # if local dotnet cli is already installed, skip
    if not os.path.exists(dotnet_cli_dir):
        # install dotnet cli locally
        log.info('Local dotnet cli install not found, launching the insallation script')
        dotnet_installer = os.path.join(correlation_dir, "RunnerScripts", "xunitrunner-perf", "ubuntu-dotnet-local-install.sh")
        log.info('Setting dotnet cli installation script at '+dotnet_installer+' as executable')
        helix.proc.run_and_log_output(("chmod 777 "+dotnet_installer).split(" "))
        log.info('Running script '+dotnet_installer)
        helix.proc.run_and_log_output((dotnet_installer+" -d "+dotnet_cli_dir+" -v "+os.path.join(correlation_dir, "RunnerScripts", "xunitrunner-perf", "DotNetCliVersion.txt")).split(" "))
    else:
        log.info('Local dotnet cli install found')

    # for dotnet to execute the dll we need the runtime files right next to the dll we need to test
    _copy_files_to_dest(core_root, test_location)

def _prepare_windows_env_for_perf(xunit_perf_drop, test_location):
    shutil.copy2(os.path.join(xunit_perf_drop, "xunit.performance.run.exe"), test_location)
    shutil.copy2(os.path.join(xunit_perf_drop, "xunit.performance.metrics.dll"), test_location)
    shutil.copy2(os.path.join(xunit_perf_drop, "xunit.performance.logger.exe"), test_location)
    shutil.copy2(os.path.join(xunit_perf_drop, "xunit.runner.utility.desktop.dll"), test_location)
    shutil.copy2(os.path.join(xunit_perf_drop, "ProcDomain.dll"), test_location)
    shutil.copy2(os.path.join(xunit_perf_drop, "Microsoft.Diagnostics.Tracing.TraceEvent.dll"), test_location)

# used to copy the required xunit perf runner an its dependencies
# note that the perf runner will only be present for perf tests.
def _prepare_perf_execution_environment(settings, perf_runner, osgroup):
    correlation_dir = fix_path(settings.correlation_payload_dir)
    test_location = os.path.join(fix_path(settings.workitem_working_dir), 'execution')
    core_root = os.path.join(settings.workitem_working_dir, 'core_root')
    os.environ['CORE_ROOT'] = core_root
    xunit_perf_drop = os.path.join(correlation_dir, perf_runner)
    if not os.path.exists(xunit_perf_drop):
        raise Exception("Failed to find perf runner {} in directory {}.".format(perf_runner, correlation_dir))