import subprocess
import io
import codecs
import os
import yaml
import sys
import os.path
from datetime import datetime
from threading import Thread

from tsuru_unit_agent.stream import Stream


def process_output(in_fd, out_fd):
    for line in iter(in_fd.readline, b''):
        if line is None:
            break
        out_fd.write(line)
    out_fd.flush()
    in_fd.close()


def exec_with_envs(commands, with_shell=False, working_dir="/home/application/current", pipe_output=False):
    if not os.path.exists(working_dir):
        working_dir = "/"
    for command in commands:
        popen_output = None
        if pipe_output:
            popen_output = subprocess.PIPE
        pipe = subprocess.Popen(command, shell=with_shell, cwd=working_dir, env=os.environ,
                                stdout=popen_output, stderr=popen_output)
        if pipe_output:
            stdout = Stream(echo_output=sys.stdout,
                            default_stream_name='stdout',
                            watcher_name='unit-agent')
            stderr = Stream(echo_output=sys.stderr,
                            default_stream_name='stderr',
                            watcher_name='unit-agent')
            stdout_thread = Thread(target=process_output, args=(pipe.stdout, stdout))
            stdout_thread.start()
            stderr_thread = Thread(target=process_output, args=(pipe.stderr, stderr))
            stderr_thread.start()
        status = pipe.wait()
        if pipe_output:
            stdout_thread.join()
            stderr_thread.join()
        if status != 0:
            sys.exit(status)


def execute_start_script(start_cmd):
    exec_with_envs([start_cmd], with_shell=True)


def run_build_hooks(app_data):
    commands = (app_data.get('hooks') or {}).get('build') or []
    exec_with_envs(commands, with_shell=True)


def run_restart_hooks(position, app_data):
    restart_hook = (app_data.get('hooks') or {}).get('restart') or {}
    commands = restart_hook.get('{}-each'.format(position)) or []
    commands += restart_hook.get(position) or []
    exec_with_envs(commands, with_shell=True, pipe_output=True)


def load_app_yaml(working_dir="/home/application/current"):
    files_name = ["tsuru.yaml", "tsuru.yml", "app.yaml", "app.yml"]
    for file_name in files_name:
        try:
            fullpath = os.path.join(working_dir, file_name)
            with codecs.open(fullpath, 'r', encoding='utf-8', errors='ignore') as f:
                return yaml.load(f.read()) or {}
        except IOError:
            pass
    return {}


def save_apprc_file(environs):
    with io.open("/home/application/apprc", "w") as file:
        file.write(u"# generated by tsuru at {}\n".format(datetime.now()))
        for env in environs:
            file.write(u'export {}="{}"\n'.format(env["name"], env["value"]))
