import json
import os
import zipfile
from html import escape

class DicEntry:
    def __init__(self, word, reading, tag="", definition=None):
        self.word = word
        self.reading = reading
        self.tag = tag
        self.content = []
        self.structured_content = False
        if definition:
            self.set_simple_content(definition)

    def to_list(self):
        if self.structured_content:
            content = [{"type": "structured-content", "content": self.content}]
        else:
            content = self.content
        return [
            self.word,
            self.reading,
            self.tag,
            "",
            0,
            content,
            0,
            ""
        ]

    def add_element(self, element):
        self.validate_element(element)
        self.content.append(element)
        self.structured_content = True

    def set_simple_content(self, definition):
        if isinstance(definition, str):
            self.content = [definition]
        elif isinstance(definition, list):
            self.content = definition
        else:
            raise ValueError("Definition must be a string or a list of strings")
        self.structured_content = False

    def set_link_content(self, definition, link):
        self.content = [
            create_html_element("ul", [
                create_html_element("li", definition)
            ]),
            create_html_element("ul", [
                create_html_element("li", [create_html_element("a", link, href=link)])
            ], style={"listStyleType": "\"⧉\""})
        ]
        self.structured_content = True

    def validate_element(self, element):
        allowed_elements = ["br", "ruby", "rt", "rp", "table", "thread", "tbody", "tfoot", "tr", "td", "th", "span", "div", "ol", "ul", "li", "img", "a"]
        if element["tag"] not in allowed_elements:
            raise ValueError(f"Unsupported HTML element: {element['tag']}")
        if "content" in element:
            if isinstance(element["content"], list):
                for child_element in element["content"]:
                    self.validate_element(child_element)
            elif not isinstance(element["content"], str):
                raise ValueError("Content must be a string or a list of elements")

class Dictionary:
    def __init__(self, dictionary_name):
        self.dictionary_name = dictionary_name
        self.entries = []

    def add_entry(self, entry):
        self.entries.append(entry)

    def export(self):
        folder_name = self.dictionary_name
        os.makedirs(folder_name, exist_ok=True)

        # Save index.json
        index_json = {
            "title": self.dictionary_name,
            "format": 3,
            "revision": "1"
        }
        index_file = os.path.join(folder_name, "index.json")
        with open(index_file, 'w', encoding='utf-8') as out_file:
            json.dump(index_json, out_file, ensure_ascii=False)

        file_counter = 1
        entry_counter = 0
        dictionary = []
        entry_id = 0

        for entry in self.entries:
            entry_list = entry.to_list()
            entry_list[6] = entry_id
            dictionary.append(entry_list)
            entry_counter += 1
            entry_id += 1

            if entry_counter >= 10000:
                output_file = os.path.join(folder_name, f"term_bank_{file_counter}.json")
                with open(output_file, 'w', encoding='utf-8') as out_file:
                    json.dump(dictionary, out_file, ensure_ascii=False)
                dictionary = []
                file_counter += 1
                entry_counter = 0

        if dictionary:
            output_file = os.path.join(folder_name, f"term_bank_{file_counter}.json")
            with open(output_file, 'w', encoding='utf-8') as out_file:
                json.dump(dictionary, out_file, ensure_ascii=False)

    def zip(self):
        zip_file_name = f"{self.dictionary_name}.zip"
        with zipfile.ZipFile(zip_file_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk(self.dictionary_name):
                for file in files:
                    file_path = os.path.join(root, file)
                    zipf.write(file_path, os.path.relpath(file_path, self.dictionary_name))

def create_html_element(tag, content, href=None, style=None, data=None):
    element = {"tag": tag}
    if isinstance(content, str):
        element["content"] = content
    else:
        element["content"] = content
    if href:
        element["href"] = href
    if style:
        element["style"] = style
    if data:
        element["data"] = data
    return element

if __name__ == "__main__":
    dictionary = Dictionary("Example_Dictionary")

    entry = DicEntry("食べる", "たべる", tag="v5r")

    definition_element = create_html_element("ul", [
        create_html_element("li", "To eat")
    ])
    link_element = create_html_element("ul", [
        create_html_element("li", [
            create_html_element("a", "View on Jisho", href="https://jisho.org/word/食べる")
        ])
    ], style={"listStyleType": "\"⧉\""})

    entry.add_element(definition_element)
    entry.add_element(link_element)

    dictionary.add_entry(entry)

    dictionary.export()
    dictionary.zip()