#!/usr/bin/env python
#
# Copyright (c) 2022 Project CHIP Authors
#
# 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.
#
"""Hex file merger

This is a helper script for merging SS, DS and XS into a single hex file.

"""

import argparse
import os
import pathlib
import re
import sys
import zlib

import leb128
from collections import OrderedDict
from intelhex import IntelHex
from struct import pack, unpack

THREAD_FACTORY_KEY_BASE = 0x2000
MATTER_FACTORY_KEY_BASE = 0x2100


def main():
    args = parse_args()

    configs = gen_thread_factory_config()
    configs.update(gen_matter_factory_config(args.config_header))

    parse_config_args(configs, args.config)

    merged_hex = insert_config(IntelHex(str(args.ss_hex)), configs)
    merged_hex.merge(IntelHex(str(args.ds_hex)))
    merged_hex.merge(IntelHex(str(args.xs_hex)))
    merged_hex.write_hex_file(args.output)


def parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument("--output", required=True, type=pathlib.Path)
    parser.add_argument("--ss_hex", required=True, type=pathlib.Path)
    parser.add_argument("--ds_hex", required=True, type=pathlib.Path)
    parser.add_argument("--xs_hex", required=True, type=pathlib.Path)
    parser.add_argument("--config_header", required=True, type=pathlib.Path)
    parser.add_argument("--config", action="append", type=str)
    return parser.parse_args()


def gen_thread_factory_config() -> OrderedDict:
    configs = OrderedDict()
    configs["ExtendedAddress"] = {"key": THREAD_FACTORY_KEY_BASE, "value": os.urandom(8)}
    return configs


def gen_matter_factory_config(path: pathlib.Path) -> OrderedDict:
    # compile the regex for extracting name and key of factory configurations.
    factory_config_re = re.compile(r"""
      .*                    # Prefix
      kConfigKey_(\w+)      # Parse the config name
      \s*=.*                # Allow spaces
      kChipFactory_KeyBase  # Only match factory configurations
      \s*,\s*               # Allow spaces
      (0x[0-9a-fA-F]+)      # Parse the config key
    """, re.VERBOSE)

    configs = OrderedDict()
    with open(str(path), mode="r") as config_file:
        for line in config_file:
            match = factory_config_re.match(line.strip())
            if match:
                name = match[1]
                key = MATTER_FACTORY_KEY_BASE + int(match[2], 0)
                configs[name] = {"key": key}
    return configs


def parse_config_args(configs: OrderedDict, args: list):
    for arg in args:
        name, category, value = arg.split(":")

        if name not in configs:
            print(f"[Warning] Ignored unknown config: {name}")
            continue

        if category == "address":
            addr = bytearray.fromhex(value)

            if len(addr) == 6:
                # RFC 4291 Appendix A
                addr[3:3] = b'\xff\xfe'
            elif len(addr) != 8:
                print(f"[Warning] Ignored config {name}: Invalid length: {len(addr)}")
                return

            configs[name]["value"] = addr[::-1]
        elif category == "file":
            with open(value, mode="rb") as file:
                configs[name]["value"] = file.read()
        else:
            print(f"[Warning] Ignored config {name}: Invalid category: {category}")


def insert_config(origin_hex: IntelHex, configs: OrderedDict):
    ss_segment = origin_hex.segments()[0]

    origin_ss_header = origin_hex.tobinarray(
        start=ss_segment[0], end=ss_segment[0] + 0x10 - 1)
    origin_ss_data = origin_hex.tobinarray(
        start=ss_segment[0] + 0x10, end=ss_segment[1] - 1)

    signature, _, _ = unpack("<8sLL", origin_ss_header)

    ss_data = bytearray()
    for config in configs.values():
        if "value" in config:
            ss_data += config["key"].to_bytes(2, byteorder="little")
            ss_data += leb128.u.encode(len(config["value"]))
            ss_data += config["value"]
    ss_data += origin_ss_data

    ss_header = pack("<8sLL", signature, zlib.crc32(ss_data), len(ss_data))

    ss_hex = IntelHex()
    ss_hex.puts(ss_segment[0], ss_header + ss_data)
    return ss_hex


if __name__ == "__main__":
    main()
