import collections
import json
import os

from ._py_components_generation import (
    generate_class_file,
    generate_imports,
    generate_classes_files,
    generate_class,
)
from .base_component import ComponentRegistry


def _get_metadata(metadata_path):
    # Start processing
    with open(metadata_path, encoding="utf-8") as data_file:
        json_string = data_file.read()
        data = json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode(
            json_string
        )
    return data


def load_components(metadata_path, namespace="default_namespace"):
    """Load React component metadata into a format Dash can parse.

    Usage: load_components('../../component-suites/lib/metadata.json')

    Keyword arguments:
    metadata_path -- a path to a JSON file created by
    [`react-docgen`](https://github.com/reactjs/react-docgen).

    Returns:
    components -- a list of component objects with keys
    `type`, `valid_kwargs`, and `setup`.
    """

    # Register the component lib for index include.
    ComponentRegistry.registry.add(namespace)
    components = []

    data = _get_metadata(metadata_path)

    # Iterate over each property name (which is a path to the component)
    for componentPath in data:
        componentData = data[componentPath]

        # Extract component name from path
        # e.g. src/components/MyControl.react.js
        # TODO Make more robust - some folks will write .jsx and others
        # will be on windows. Unfortunately react-docgen doesn't include
        # the name of the component atm.
        name = componentPath.split("/").pop().split(".")[0]
        component = generate_class(
            name, componentData["props"], componentData["description"], namespace, None
        )

        components.append(component)

    return components


def generate_classes(namespace, metadata_path="lib/metadata.json"):
    """Load React component metadata into a format Dash can parse, then create
    Python class files.

    Usage: generate_classes()

    Keyword arguments:
    namespace -- name of the generated Python package (also output dir)

    metadata_path -- a path to a JSON file created by
    [`react-docgen`](https://github.com/reactjs/react-docgen).

    Returns:
    """

    data = _get_metadata(metadata_path)
    imports_path = os.path.join(namespace, "_imports_.py")

    # Make sure the file doesn't exist, as we use append write
    if os.path.exists(imports_path):
        os.remove(imports_path)

    components = generate_classes_files(namespace, data, generate_class_file)

    # Add the __all__ value so we can import * from _imports_
    generate_imports(namespace, components)
