#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed 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.

import tempfile
import re
import subprocess
import io
import argparse
import os
import sys
import stat


sys.path.append(
    os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__)))))
from scripts.util import build_utils


def host_triple(rustc_path):
    known_vars = dict()
    args = [rustc_path, "-vV"]
    proc = subprocess.Popen(args, stdout=subprocess.PIPE)
    for lines in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
        rustc_version = re.compile(r"(\w+): (.*)")
        match = rustc_version.match(lines.rstrip())
        if match:
            known_vars[match.group(1)] = match.group(2)
    proc.wait()
    return known_vars.get("host")


def run_build_script(args, env, tempdir):
    process = subprocess.run([os.path.abspath(args.build_script)],
                             env=env,
                             cwd=args.src_dir,
                             encoding='utf8',
                             capture_output=True)

    if process.stderr.rstrip():
        print(process.stderr.rstrip(), file=sys.stderr)
    process.check_returncode()

    flags = ""
    for line in process.stdout.split("\n"):
        rustc_cfg = re.compile("cargo:rustc-cfg=(.*)")
        match = rustc_cfg.match(line.rstrip())
        if match:
            flags = "%s--cfg\n%s\n" % (flags, match.group(1))

    with build_utils.atomic_output(args.output) as output:
        output.write(flags.encode("utf-8"))

    if args.generated_files:
        for generated_file in args.generated_files:
            input_path = os.path.join(tempdir, generated_file)
            output_path = os.path.join(args.out_dir, generated_file)
            out_dir = os.path.dirname(output_path)
            if not os.path.exists(out_dir):
                os.makedirs(out_dir, exist_ok=True)
            with os.fdopen(os.open(input_path,
                                   os.O_RDWR | os.O_CREAT, stat.S_IWUSR | stat.S_IRUSR),
                           'rb') as inputs:
                with build_utils.atomic_output(output_path) as output:
                    content = inputs.read()
                    output.write(content)


def set_env(args, rustc_path, tempdir):
    rustc_abs_path = os.path.abspath(rustc_path)
    src_dir_abs_path = os.path.abspath(args.src_dir)

    env = {
        "RUSTC": rustc_abs_path,
        "HOST": host_triple(rustc_abs_path),
        "CARGO_MANIFEST_DIR": src_dir_abs_path,
        "OUT_DIR": tempdir,
    }
    if args.target:
        env["TARGET"] = args.target
    else:
        env["TARGET"] = env.get("HOST")

    env["CARGO_CFG_TARGET_ARCH"], *_ = env.get("TARGET").split("-")
    if args.env:
        env.update({key: val for key, val in (e.split('=') for e in args.env)})
    if args.features:
        for feature in args.features:
            feature_name = feature.replace("-", "_").upper()
            env[f"CARGO_FEATURE_{feature_name}"] = "1"

    rust_log = os.environ.get("RUST_LOG")
    rust_bt = os.environ.get("RUST_BACKTRACE")

    if rust_log:
        env["RUST_LOG"] = rust_log
    if rust_bt:
        env["RUST_BACKTRACE"] = rust_bt

    return env


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--build-script',
                        required=True,
                        help='build script needed to run')
    parser.add_argument('--target', help='rust target triple')
    parser.add_argument('--features', help='features', nargs='+')
    parser.add_argument('--env', help='environment variable', nargs='+')
    parser.add_argument('--output',
                        required=True,
                        help='where to write output rustc flags')
    parser.add_argument('--rust-prefix', required=True,
                        help='rust path prefix')
    parser.add_argument('--generated-files', nargs='+',
                        help='any generated file')
    parser.add_argument('--out-dir', required=True, help='ohos target out dir')
    parser.add_argument('--src-dir', required=True,
                        help='ohos target source dir')

    args = parser.parse_args()
    rustc_path = os.path.join(args.rust_prefix, "rustc")
    with tempfile.TemporaryDirectory() as tempdir:
        env = set_env(args, rustc_path, tempdir)
        run_build_script(args, env, tempdir)


if __name__ == '__main__':
    sys.exit(main())