# ========================== begin_copyright_notice ============================
#
# Copyright (C) 2017-2021 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
# =========================== end_copyright_notice =============================

import binascii
import os
import re
import sys




def PrintHelp():
    sys.stdout.write('Usage: {0} <input file> <output file> <symbol name> <attribute>\n'.format(os.path.basename(__file__)))
    sys.stdout.write('\n')
    sys.stdout.write('    <input file>  - Path to input file which will be embedded.\n')
    sys.stdout.write('    <output file> - Path to output .cpp file which embedded data\n')
    sys.stdout.write('                    will be written to.\n')
    sys.stdout.write('    <symbol name> - Base name of symbol which identifies embedded data.\n')
    sys.stdout.write('    <attribute>   - "visibility" to add visibility attribute, "no_attr" to add no attribute\n')




class ResEmb:
    def __init__(self, inFile, outFile, symName, attrOpt):
        self.__symRe = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
        self.__lineSize = 20
        self.__chunkSize = 131072
        self.__symName = symName
        self.__attrOpt = attrOpt
        self.__openedFiles = list()
        self.__attr = ""
        self.__validate()
        try:
            self.__inFile = open(inFile, 'rb')
        # Note: open can throw OSError or IOError on Windows
        except EnvironmentError as ex:
            sys.stderr.write('ERROR: Cannot open input file "{0}".\n           {1}.\n'.format(inFile, ex.strerror))
            raise RuntimeError("failed to open input file")
        self.__openedFiles.append(self.__inFile)
        try:
            self.__outFile = open(outFile, 'w')
        except EnvironmentError as ex:
            sys.stderr.write('ERROR: Cannot create/open output file "{0}".\n       {1}.\n'.format(outFile, ex.strerror))
            raise RuntimeError("failed to open output file")
        self.__openedFiles.append(self.__outFile)

    def __del__(self):
        for openedFile in self.__openedFiles:
            openedFile.close()
    def __validate(self):
        symName = self.__symName
        if not self.__symRe.match(symName) or symName.endswith('_size'):
            sys.stderr.write('ERROR: Invalid symbol name "{0}".\n'.format(symName))
            raise ValueError

        attrOpt = self.__attrOpt
        if attrOpt == "visibility":
            self.__attr = '__attribute__((visibility("default")))'
        elif attrOpt == "no_attr":
            self.__attr = ""
        else:
            sys.stderr.write('ERROR: Invalid attribute argument: "{0}".\n'.format(attrOpt))
            raise ValueError

    def run(self):
        self.__outFile.write('// This file is auto generated by resource_embedder, DO NOT EDIT\n\n')
        self.__outFile.write('unsigned char {0} {1}[] = {{'.format(self.__attr, self.__symName))

        chunkSize = self.__chunkSize
        lineSize = self.__lineSize
        embeddedSize = 0;
        readBytes = self.__inFile.read(chunkSize)
        while len(readBytes) > 0:
            readSize = len(readBytes)
            hexBytes = binascii.hexlify(readBytes)

            if embeddedSize > 0:
                self.__outFile.write(',')
            self.__outFile.write(','.join((('\n        0x' if (embeddedSize + i) % lineSize == 0 else ' 0x') + hexBytes[2*i:2*i+2].decode("utf-8")) for i in range(readSize)))

            embeddedSize += readSize
            readBytes = self.__inFile.read(chunkSize)

        self.__outFile.write('\n    };\n\n');
        self.__outFile.write('unsigned int {0} {1}_size = {2};\n\n'.format(self.__attr, self.__symName, embeddedSize))


if __name__ == "__main__":
    numArgs = 5
    if len(sys.argv) < numArgs:
        PrintHelp()
        exit(0)
    for arg in sys.argv:
        if arg == '-h' or arg == '--help':
            PrintHelp()
            exit(0)

    if len(sys.argv) > numArgs:
        sys.stderr.write('WARNING: Number of arguments is greater than number of supported arguments.\n')
        sys.stderr.write('         All additional arguments will be ignored.\n')

    try:
        RE = ResEmb(sys.argv[1], sys.argv[2], sys.argv[3].strip(),
                sys.argv[4].strip())
        RE.run()

    except Exception as ex:
        sys.stderr.write('ERROR: Embeded script error.\n       {0}.\n'.format(repr(ex)))
        exit(1)

