# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Local execution of operations.
"""

import os
import subprocess
import threading
import StringIO

from . import ctx_proxy
from . import exceptions
from . import common
from . import constants
from . import environment_globals
from . import python_script_scope


def run_script(ctx, script_path, process, **kwargs):
    if not script_path:
        ctx.task.abort('Missing script_path')
    process = process or {}
    script_path = common.download_script(ctx, script_path)
    script_func = _get_run_script_func(script_path, process)
    return script_func(
        ctx=ctx,
        script_path=script_path,
        process=process,
        operation_kwargs=kwargs)


def _get_run_script_func(script_path, process):
    if _treat_script_as_python_script(script_path, process):
        return _eval_script_func
    else:
        if _treat_script_as_powershell_script(script_path):
            process.setdefault('command_prefix', constants.DEFAULT_POWERSHELL_EXECUTABLE)
        return _execute_func


def _treat_script_as_python_script(script_path, process):
    eval_python = process.get('eval_python')
    script_extension = os.path.splitext(script_path)[1].lower()
    return (eval_python is True or (script_extension == constants.PYTHON_SCRIPT_FILE_EXTENSION and
                                    eval_python is not False))


def _treat_script_as_powershell_script(script_path):
    script_extension = os.path.splitext(script_path)[1].lower()
    return script_extension == constants.POWERSHELL_SCRIPT_FILE_EXTENSION


def _eval_script_func(script_path, ctx, operation_kwargs, **_):
    with python_script_scope(operation_ctx=ctx, operation_inputs=operation_kwargs):
        execfile(script_path, environment_globals.create_initial_globals(script_path))


def _execute_func(script_path, ctx, process, operation_kwargs):
    os.chmod(script_path, 0755)
    process = common.create_process_config(
        script_path=script_path,
        process=process,
        operation_kwargs=operation_kwargs)
    command = process['command']
    env = os.environ.copy()
    env.update(process['env'])
    ctx.logger.info(u'Executing: {0}'.format(command))
    with ctx_proxy.server.CtxProxy(ctx, common.patch_ctx) as proxy:
        env[ctx_proxy.client.CTX_SOCKET_URL] = proxy.socket_url
        running_process = subprocess.Popen(
            command,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            env=env,
            cwd=process.get('cwd'),
            bufsize=1,
            close_fds=not common.is_windows())
        stdout_consumer = _OutputConsumer(running_process.stdout)
        stderr_consumer = _OutputConsumer(running_process.stderr)
        exit_code = running_process.wait()
    stdout_consumer.join()
    stderr_consumer.join()
    ctx.logger.info(u'Execution done (exit_code={0}): {1}'.format(exit_code, command))

    def error_check_func():
        if exit_code:
            raise exceptions.ProcessException(
                command=command,
                exit_code=exit_code,
                stdout=stdout_consumer.read_output(),
                stderr=stderr_consumer.read_output())
    return common.check_error(ctx, error_check_func=error_check_func)


class _OutputConsumer(object):

    def __init__(self, out):
        self._out = out
        self._buffer = StringIO.StringIO()
        self._consumer = threading.Thread(target=self._consume_output)
        self._consumer.daemon = True
        self._consumer.start()

    def _consume_output(self):
        for line in iter(self._out.readline, b''):
            self._buffer.write(line)
        self._out.close()

    def read_output(self):
        return self._buffer.getvalue()

    def join(self):
        self._consumer.join()
