#!/usr/bin/env python

import os
import sys
import argparse
import yaml


def fix_sys_path():
    # For debug runs wih 'python -m pdb'
    from logging import NullHandler, getLogger
    getLogger("devtools.fleur.imports.path").addHandler(NullHandler())  # suppress fleur logging
    import arcadia    # Access arcadia source tree / if not found, see https://nda.ya.ru/3Tknpm
    from devtools.fleur.imports.arcadiahook import GetArcadiaPath
    sys.path.insert(0, os.path.join(GetArcadiaPath(), "devtools", "ya"))
    arcadia.use()
# fix_sys_path()     # uncomment

from urlparse import urlsplit
import search.tools.devops.libs.nanny_services as ns
from yalibrary.yandex import sandbox
from yalibrary.yandex.sandbox import fetcher


def soft_rm_dir(path):
    if os.path.isdir(path):
        for f in os.listdir(path):
            os.remove(os.path.join(path, f))
        os.rmdir(path)


def rm_dir(path):
    for root, dirs, files in os.walk(path, topdown=False):
        for name in files:
            os.remove(os.path.join(root, name))
        for name in dirs:
            os.rmdir(os.path.join(root, name))


def fetch_sandbox_resource(res_id, fname):
    res_info = client.get_resource(res_id)
    resource_file_name = os.path.basename(res_info["file_name"])

    fetcher.download_resource(res_id, tmpdir, ["skynet", "http"])
    os.rename(os.path.join(tmpdir, resource_file_name), fname)
    os.chmod(fname, 0775)


def get_sandbox_resid_from_nanny(service, res_name):
    if res_name.startswith("/"):
        res_name = res_name[1:]
    response = ns.get_service_runtime_attrs(service)
    sandbox_resources = response.json()["content"]["resources"]["sandbox_files"]
    match = next((item["resource_id"] for item in sandbox_resources if item["local_path"] == res_name), None)
    if not match:
        raise ValueError("Resource {} not found in service {} (the entry is not present or not from Sandbox)".format(res_name, service))
    return match


class SandboxResource(object):
    def __init__(self, res_id):
        self.res_id = res_id

    def fetch(self, fname):
        fetch_sandbox_resource(self.res_id, fname)


def resolve_uri(uri):
    data = urlsplit(uri)
    if data.scheme == "sbr":
        return SandboxResource(int(data.netloc))
    if data.scheme == "nanny":
        res_id = get_sandbox_resid_from_nanny(data.netloc, data.path)
        return SandboxResource(res_id)

    raise ValueError("Unknown scheme: " + data.scheme)


msg_no_oauth_token = """
You need to have OAUTH_NANNY defined.

1. Go to https://nanny.yandex-team.ru/ui/#/oauth/
2. Run
    read OAUTH_NANNY; export OAUTH_NANNY
3. Copy and paste your token into the console, press Enter
   (this way the token is not logged anywhere)
"""


def check_env():
    token = os.environ.get("OAUTH_NANNY", None)
    if not token:
        print >> sys.stderr, msg_no_oauth_token
        return False
    return True

if __name__ == "__main__":
    description = "Fetches binaries into a workcopy from sandbox, nanny services etc."
    parser = argparse.ArgumentParser(description=description)
    parser.add_argument("-c", dest="config", default="config.yaml", help="config file to use")
    parser.add_argument("--target", default="binaries", help="target dir")

    args = parser.parse_args()
    config_file = args.config

    if not check_env():
        sys.exit(1)

    target = args.target
    print >> sys.stderr, "Fetching binaries as specified in {} into '{}'".format(config_file, target)

    with open(config_file, "r") as config_stream:
        config = yaml.load(config_stream)

    config_timestamp = os.path.getmtime(config_file)

    rootdir = os.getcwd()
    tmpdir = os.path.join(rootdir, ".tmp")
    rm_dir(tmpdir)
    os.makedirs(tmpdir)
    os.chdir(target)

    client = sandbox.SandboxClient()

    for kv in config['binaries'].iteritems():
        fname = kv[0]
        if os.path.exists(fname):
            # if os.path.getmtime(fname) > config_timestamp:
            #     sys.stderr.write("{}\tnot updated - file is newer than {}\n".format(fname, config_file))
            #     continue
            # os.remove(fname)
            sys.stderr.write("{:<28}\talready exists\n".format(fname))
            continue

        uri = kv[1]
        sys.stderr.write("{:<28}\tGetting {}...".format(fname, uri))
        resource = resolve_uri(uri)
        resource.fetch(fname)
        sys.stderr.write("Done\n")

    os.chdir(rootdir)
