import os
from enum import  Enum
import datetime
import unicodedata

class  Format_type(Enum):
    N=1
    C=2
class  Format_val(Enum):
    I=1
    V=2

class Fmt:

    def __init__(self,name,desc,is_write):
        self.name=name
        self.desc=desc
        self.is_extensible=is_write
        self.fmt_type=Format_type.C
        self.fmt_value=Format_val.V
        self.category=""
        self.category_desc=""
        self.dictvals = []

    def add_members(self,start,label):
        self.dictvals.append( (start,label))

    @staticmethod
    def write_catalog(format_list,fn):
        # datetime.datetime.now(): % d - % b - % Y
        with open(fn, 'w') as f:
            f.write(f"*{'-'*73}*\n")
            f.write('|' + " SAS Formats Catalog\n")
            f.write('|' + f" Path: {fn}\n")
            f.write('|' + f" Autogenerated by Candid on: {datetime.datetime.now().strftime('%d-%b-%Y')}\n")
            f.write(f"| {'-' * 10} Post-testing modifications {'-' * 10}\n")
            f.write("|  Date        User        Modification\n|\n")
            f.write(f"*{'-'*73}*;\n")
            f.write("%include 'init.sas'\n\n")

            # delete existing catalogs
            f.write("proc datasets library=out memtype=catalog;\n\tdelete formats;\nrun;\n\n")

            f.write("proc format library=out;\n")

            for i in format_list:

                # Write the invalue statement
                f.write(Fmt.write_comment(i))

                # Write the invalue statement
                if i.fmt_type==Format_val.I:
                    f.write("\tinvalue")
                    if i.fmt_type==Format_type.N:
                        f.write(f" ${i.name + '_' + i.category}\n")
                    else:
                        f.write(f" {i.name+ '_' + i.category}\n")

                # Write the value statement
                else:
                    if i.fmt_type==Format_type.C:
                        f.write(f"\tvalue ${i.name + '_' + i.category}\n")
                    else:
                        f.write(f"\tvalue {i.name + '_' + i.category}\n")

                # Loop for each member of format catalog
                for j in i.dictvals:
                    # start
                    if i.fmt_type==Format_type.N:
                        f.write(f"\t\t{remove_cc(j[0])} = ")
                    else:
                        f.write(f"\t\t\"{remove_cc(j[0])}\" = ")
                    # label
                    if i.fmt_type == Format_val.I:
                        f.write(f"{remove_cc(j[1])}\n")
                    else:
                        f.write(f'"{remove_cc(j[1])}"\n')
                f.write("\t\t;\n")
            f.write("run;")






    @staticmethod
    def write_comment(fmt):
        # Break text into max segments
        fit_txt=[fmt.desc[i:i+65] for i in range(0, len(fmt.desc), 65)]

        com_txt=[]
        com_txt.append(f"\t*{'-' * 68}*")
        com_txt.append(f"\t|Format: {fmt.name}\n\t|Extensible:{fmt.is_extensible}")
        com_txt.append(f"\t|Description:")
        [com_txt.append(f"\t| {i}") for i in fit_txt]
        com_txt.append(f"\t*{'-' * 68}*;\n")

        return "\n".join(com_txt)





def remove_cc(s):
    return "".join(ch for ch in s if unicodedata.category(ch)[0]!="C")





