import * as React from "react";
import * as _ from "lodash";
import styled, { StyledComponentClass } from "styled-components";
import DefaultCheckBox, { CheckBox } from "../Checkbox";
import { COLOR_PALETTE } from "../../constants/colors";
import * as DefaultStyles from "./style";

import { CheckItem } from "../../types/global"


export namespace HierarchyList {
    export interface State {
        openItems: { id: boolean };
    }
    /**
     * TODO: We need the check clicked, items, and checkedItems props to be required
     * right now they are optional for if you want to use this component to make a custom layout
     * for the list picker you don't need to initalize the default props because the list picker does that
     * Want to have an internal/external representation of this component with the req/optional props
     */
    export interface Props {
        checkClicked?: (item) => void;
        items?: CheckItem[];
        styles?: HierarchyList.Styles;
        checkedItems?: CheckItem[];
        keyPrefix?: string;
        readonly?: boolean;
        checkBox?: (props: CheckBox.Props) => JSX.Element;
        id?: string;
        name?: string;
    }

    export interface Styles {
        CheckListOuterContainer?: any;
        CheckListContainer?: any;
        ChildrenContainer?: any;
        CheckItemContainer?: any;
        Value?: any;
        RotatingArrow?: any;
    }
}

const defaultState = {
    openItems: { id: false },
};

class HierarchyList extends React.Component<
    HierarchyList.Props,
    HierarchyList.State
    > {

    constructor(props: HierarchyList.Props) {
        super(props);
        this.state = defaultState;
    }

    private toggleOpen = (id: string): void => {
        const openItems = _.clone(this.state.openItems);
        openItems[id] = !openItems[id];
        this.setState({ openItems });
    };

    private isSelected(id: string): boolean {
        return Boolean(
            this.props.checkedItems &&
            this.props.checkedItems.find(item => item.id === id)
        );
    }

    private renderChildren = (Styles: HierarchyList.Styles, item: CheckItem, indentation: number) => {
        const open = this.state.openItems[item.id];
        const hasChildren = Boolean(item.children.length);
        const CheckBox = this.props.checkBox || DefaultCheckBox;
        const key = `${this.props.keyPrefix}-${item.id}`;
        return (
            <React.Fragment key={key} >
                <Styles.CheckItemContainer
                    className="check-item-container"
                    data-testid={item.id}
                    onClick={() => this.toggleOpen(item.id)}
                    clickable={hasChildren}
                    indentation={indentation}
                    bgColor={
                        indentation
                            ? COLOR_PALETTE.BLUE_LIGHT_1
                            : COLOR_PALETTE.BLUE_LIGHT_4
                    }
                    id={this.props.id && this.props.id + '-check-item-container'}
                    name={this.props.name && this.props.name + '-check-item-container'}
                >
                    <Styles.Value className="check-item-value-container" id={this.props.id && this.props.id + '-check-item-value-container'} name={this.props.name && this.props.name + '-check-item-value-container'}>
                        <CheckBox
                            readonly={this.props.readonly}
                            onChange={() =>
                                this.props.checkClicked
                                    ? this.props.checkClicked(item)
                                    : null
                            }
                            value={this.isSelected(item.id)}
                            id={this.props.id ? this.props.id : item.name}
                            name={this.props.name && this.props.name}
                        />
                        <Styles.Value className="check-item-value" id={this.props.id && this.props.id + '-value-span'} name={this.props.name && this.props.name + '-value-span'}>
                            {item.name}
                        </Styles.Value>
                    </Styles.Value>
                    {hasChildren && (
                        <Styles.RotatingArrow
                            className="rotating-arrow"
                            activeState={open}
                            id={this.props.id && this.props.id + '-rotating-arrow'}
                            name={this.props.name && this.props.name + '-rotating-arrow'}

                        />
                    )}
                </Styles.CheckItemContainer>
                <Styles.ChildrenContainer className="check-list-child-contaniner" id={this.props.id && this.props.id + '-check-list-child-contaniner'} name={this.props.name && this.props.name + '-check-list-child-contaniner'}>
                    {open &&
                        item.children.map(child =>
                            this.renderChildren(Styles, child, indentation + 1)
                        )}
                </Styles.ChildrenContainer>
            </React.Fragment>
        );
    };

    public render(): JSX.Element {
        const Styles: HierarchyList.Styles = _.merge(DefaultStyles, this.props.styles);
        return (
            <Styles.CheckListOuterContainer id={this.props.id && this.props.id + '-hierarchy-list-outer-container'} name={this.props.name && this.props.name + '-hierarchy-list-outer-container'}>
                <Styles.CheckListContainer id={this.props.id && this.props.id + '-hierarchy-list-container'} name={this.props.name && this.props.name + '-hierarchy-list-container'}>
                    {_.map(this.props.items, item =>
                        this.renderChildren(Styles, item, 0)
                    )}
                </Styles.CheckListContainer>
            </Styles.CheckListOuterContainer>
        );
    }
}

export default HierarchyList;
