#!/usr/bin/env python3
#
#    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.
#

import codecs
import sys
from intelhex import IntelHex
import argparse
import json
import logging as log
import cbor2 as cbor

HEX_PREFIX = "hex:"


class PartitionCreator:
    """
    Class to create telink partition containing FactoryData

    :param offset: This is a partition offset where data will be stored in device's flash memory
    :param length: This is a maximum partition size
    :param input: This is a path to input JSON file
    :param output: This is a path to output directory

    """

    def __init__(self, offset: int, length: int, input: str, output: str) -> None:
        self._ih = IntelHex()
        self._length = length
        self._offset = offset
        self._data_ready = False
        self._output = output
        self._input = input
        try:
            self.__data_to_save = self._convert_to_dict(self._load_json())
        except IOError:
            sys.exit(-1)

    def generate_cbor(self):
        """
        Generates .cbor file using cbor2 library.
        It generate a CBORTag 55799 which is user-specific tag

        """
        if self.__data_to_save:
            # prepare raw data from Json
            cbor_data = cbor.dumps(self.__data_to_save)
            return cbor_data

    def create_hex(self, data: bytes):
        """
        Creates .hex file from CBOR.
        This file can be write directly to device.

        """
        if len(data) > self._length:
            raise ValueError("generated CBOR file exceeds declared maximum partition size! {} > {}".format(len(data), self._length))
        self._ih.putsz(self._offset, data)
        self._ih.write_hex_file(self._output + ".hex", True)
        self._data_ready = True
        return True

    def create_bin(self):
        """
        Creates raw binary data of created previously .hex file

        """
        if not self._data_ready:
            log.error("Please create hex file first!")
            return False
        self._ih.tobinfile(self._output + ".bin")
        return True

    @staticmethod
    def _convert_to_dict(data):
        """
        Converts a list containing tuples ("key_name", "key_value") to a dictionary

        If "key_value" of data entry is a string-type variable and contains a HEX_PREFIX algorithm decodes it 
        to hex format to be sure that a cbor file will contain proper bytes.

        If "key_value" of data entry is a dictionary, algorithm appends it to the created dictionary.
        """
        output_dict = dict()
        for entry in data:
            if not isinstance(entry, dict):
                log.debug("Processing entry {}".format(entry))
                if isinstance(data[entry], str) and data[entry].startswith(HEX_PREFIX):
                    output_dict[entry] = codecs.decode(data[entry][len(HEX_PREFIX):], "hex")
                elif isinstance(data[entry], str):
                    output_dict[entry] = data[entry].encode("utf-8")
                else:
                    output_dict[entry] = data[entry]
            else:
                output_dict[entry] = entry
        return output_dict

    def _load_json(self):
        """
        Loads file containing a JSON data and converts it to JSON format

        :raises IOError: if provided JSON file can not be read out.
        """
        try:
            with open(self._input, "rb") as json_file:
                return json.loads(json_file.read())
        except IOError as e:
            log.error("Can not read Json file {}".format(self._input))
            raise e


def print_flashing_help():
    print("\nTo flash the generated hex/bin containing factory data, use BDT tool")


def main():

    def allow_any_int(i): return int(i, 0)

    parser = argparse.ArgumentParser(description="Telink Factory Data NVS partition generator tool")
    parser.add_argument("-i", "--input", type=str, required=True,
                        help="Path to input .json file")
    parser.add_argument("-o", "--output", type=str, required=True,
                        help="Prefix for output file paths, e.g. setting dir/output causes creation of the following files: dir/output.hex, and dir/output.bin")
    parser.add_argument("--offset", type=allow_any_int, required=True,
                        help="Partition offset - an address in device's NVM memory, where factory data will be stored")
    parser.add_argument("--size", type=allow_any_int, required=True,
                        help="The maximum partition size")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Run this script with DEBUG logging level")
    parser.add_argument("-r", "--raw", action="store_true",
                        help="Do not print flashing help and other logs, only generate a .hex file. It can be useful when the script is used by other script.")
    args = parser.parse_args()

    if args.verbose:
        log.basicConfig(format='[%(asctime)s][%(levelname)s] %(message)s', level=log.DEBUG)
    elif args.raw:
        log.basicConfig(format='%(message)s', level=log.ERROR)
    else:
        log.basicConfig(format='[%(asctime)s] %(message)s', level=log.INFO)

    partition_creator = PartitionCreator(args.offset, args.size, args.input, args.output)
    cbor_data = partition_creator.generate_cbor()
    try:
        if not args.raw:
            print("Generating .hex file: {}.hex with offset: {} and size: {}".format(args.output, hex(args.offset), hex(args.size)))
        if partition_creator.create_hex(cbor_data) and partition_creator.create_bin():
            if not args.raw:
                print_flashing_help()
    except ValueError as e:
        log.error(e)
        sys.exit(-1)


if __name__ == "__main__":
    main()
