import argparse
import logging
import sys
import os
import re

copyright = "/" + "*" * 73 + "\n"
copyright += " * Copyright (C) [2023-2024] by Cambricon, Inc.\n"
copyright += " *\n"
copyright += " * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n"
copyright += " * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
copyright += " * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n"
copyright += " * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n"
copyright += " * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n"
copyright += " * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n"
copyright += " * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
copyright += " " + "*" * 73 + "/\n"

tmo_path = os.path.abspath(sys.path[0] + "../..")

def arg():
    """ Argparser. """
    parser = argparse.ArgumentParser('''
        A format script for checking cc/h is following llvm format
        or not.''')
    parser.add_argument(
        "--path", help="Location of .h/.cpp file to generate template.")
    return parser.parse_args()


class Header(object):
    """ Object to gen/check header. """

    def __init__(self, path):
        """ Init function with args. """
        # Check path first.
        self.__path = os.path.abspath(path)
        self.filename = os.path.split(path)[1]
        if path.endswith(".cpp") or path.endswith(".cc"):
            self.__has_macro = False
        elif path.endswith(".h") or path.endswith(".mluh"):
            self.__has_macro = True
        else:
            logging.info("Skip: format_checker is only for .cpp/.cc/.h")
            logging.info("But met " + self.__path)
            sys.exit(0)
        if not self.__path.startswith(tmo_path):
            logging.info("Skip: format_checker is only for genesis file")
            sys.exit(0)
        # Gen header.
        self.__regex = copyright.replace(
            "(", "\(").replace(")", "\)").replace("[", "\[").replace(
                "]", "\]").replace("-", "\-").replace("*", "\*")
        if self.__has_macro:
            file_macro = self.__path.replace(tmo_path + "/", "").replace(
                "/", "_").replace(".", "_").upper()+"_"
            self.__macro = "#ifndef " + file_macro + "\n"
            self.__macro += "#define " + file_macro + "\n"
            self.__macro += "#endif  // " + file_macro + "\n"

    def check(self):
        """ To check header/macro. """
        fo = open(self.__path, "r")
        file_string = fo.read()
        fo.close()
        ptrn_header = re.compile(self.__regex, re.DOTALL)
        h_r = ptrn_header.match(file_string)
        if not h_r:
            logging.error(args.path +
                          " header mismatch, pattern should be like:")
            logging.error("\n" + self.__regex)
            sys.exit(-1)

        if self.__has_macro:
            ptrn_macro = re.compile(".*" + self.__macro.replace("\n", "\n.*"),
                                    re.DOTALL)
            m_r = ptrn_macro.match(file_string)
            if not m_r:
              logging.error(args.path +
                                " macro mismatch, pattern should be like:")
              logging.error("\n" + self.__macro)
              sys.exit(-1)

if __name__ == "__main__":
    args = arg()
    logging.basicConfig(level=logging.INFO)
    if not os.path.exists(args.path):
        logging.info("Skip: no such file")
        sys.exit(0)
    h = Header(args.path)
    h.check()
