#!/usr/bin/env python3
#
# MIT License
#
# Copyright (c) 2020 Victor Gama de Oliveira <hey@vito.io>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

import re
from pathlib import Path


def ignorable(file):
    return file.name.endswith(".story.jsx") or \
           file.name.endswith(".style.jsx")


def extract_exports(file):
    txt = file.read_text()
    simple_exports = re.findall(r"export const ([^\s]*)", txt)
    complex_exports = re.findall(r"export {([^}]+)}", txt)
    complex_exports = [re.findall(r"([^\s,\n]+)", p)
                       for p in complex_exports]
    complex_exports = [i for l in complex_exports for i in l]
    return [exp for exp in simple_exports + complex_exports
            if re.match(r"^[A-Z]", exp)]


def split_noindex_definitions(defs):
    ignored = {f.parent for f in defs if f.stat().st_size == 0}
    top_only = {f.parent for f in defs
                if f.parent not in ignored and
                f.read_text().strip() == "top-only"}
    return (ignored, top_only)


def compile_exports(exports):
    outputs = exports.items()
    outputs = [(k, ", ".join(v)) for k, v in outputs]
    outputs = [f"import {{ {v} }} from \"{k}\"" for k, v in outputs]
    exp = ", ".join([i for l in exports.values() for i in l])
    outputs.append(f"export {{{exp}}};")
    return outputs


def run():
    target_dir = Path("./app/javascript/components")
    target = target_dir / "index.jsx"
    if target.exists():
        target.unlink()
    no_index = list(target_dir.rglob(".no-index"))
    ignored, top_only = split_noindex_definitions(no_index)

    exports = {}
    for file in target_dir.rglob("*.jsx"):
        if ignorable(file):
            continue

        parent = file.parent
        if parent in ignored or parent in top_only:
            continue

        f_name = f"/{file.name}"
        if f_name == "/index.jsx":
            f_name = ""

        exports[f"./{parent.name}{f_name}"] = extract_exports(file)

    for parent in top_only:
        file = parent / "index.jsx"
        exp = extract_exports(file)
        if len(exp) > 0:
            exports[f"./{parent.name}"] = exp
    outputs = [
        "/* eslint-disable */",
        "// Generated by index-react-components. DO NOT EDIT.",
        "// This file was generated automatically by a tool. Any changes",
        "// will be lost when it gets regenerated!",
    ] + compile_exports(exports) + [""]
    target.write_text("\n".join(outputs))


if __name__ == "__main__":
    run()