/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import React from 'react';
import {
    Button,
    Modal,
    ActionGroup,
    Text,
    CardHeader,
    CardActions,
    Badge, Flex, CardTitle,
} from '@patternfly/react-core';
import '../designer/karavan.css';
import {TableComposable, Tbody, Td, Th, Thead, Tr} from "@patternfly/react-table";
import {Component} from "karavan-core/lib/model/ComponentModels";
import {camelIcon, CamelUi} from "../designer/utils/CamelUi";
import {ComponentApi} from "karavan-core/lib/api/ComponentApi";
import {ComponentProperty} from "karavan-core/lib/model/ComponentModels";

interface Props {
    component?: Component,
    isOpen: boolean;
}

interface State {
    isOpen: boolean;
    component?: Component,
}

export class ComponentModal extends  React.Component<Props, State> {

    public state: State = {
        isOpen: this.props.isOpen,
        component: this.props.component,
    };

    setModalOpen = (open: boolean) => {
        this.setState({isOpen: false});
    }

    componentDidUpdate = (prevProps: Readonly<Props>, prevState: Readonly<State>, snapshot?: any) => {
        if (prevState.isOpen !== this.props.isOpen) {
            this.setState({isOpen: this.props.isOpen});
        }
    }

    render() {
        const component = this.state.component;
        const props = new Map<string, ComponentProperty>();
        if (component){
            ComponentApi.getComponentProperties(component?.component.name, "consumer").forEach(cp => props.set(cp.name, cp));
            ComponentApi.getComponentProperties(component?.component.name, "producer").forEach(cp => props.set(cp.name, cp));
        }
        return (
            <Modal
                aria-label={"Kamelet"}
                width={'fit-content'}
                maxLength={200}
                title={component?.component.title}
                isOpen={this.state.isOpen}
                onClose={() => this.setModalOpen(false)}
                actions={[
                    <div className="modal-footer">
                        <ActionGroup className="deploy-buttons">
                            <Button key="cancel" variant="primary"
                                    onClick={e => this.setModalOpen(false)}>Close</Button>
                        </ActionGroup>
                    </div>
                ]}
            >
                <Flex direction={{default: 'column'}} key={component?.component.name}
                      className="kamelet-modal-card">
                    <CardHeader>
                        {CamelUi.getIconFromSource(camelIcon)}
                        <CardActions>
                            <Badge className="badge"
                                   isRead> {component?.component.label}</Badge>
                        </CardActions>
                    </CardHeader>
                    <Text className="description">{component?.component.description}</Text>
                    {props.size !== 0 &&
                    <div>
                        <CardTitle>Properties</CardTitle>
                        <TableComposable aria-label="Simple table" variant='compact'>
                            <Thead>
                                <Tr>
                                    <Th key='name'>Display Name / Name</Th>
                                    <Th key='desc'>Description</Th>
                                    <Th key='type'>Type</Th>
                                    <Th key='label'>Label</Th>
                                </Tr>
                            </Thead>
                            <Tbody>
                                {Array.from(props.values()).map((p: ComponentProperty, idx: number) => (
                                    <Tr key={idx}>
                                        <Td key={`${idx}_name`}>
                                            <div>
                                                <b>{p.displayName}</b>
                                                <div>{p.name}</div>
                                            </div>
                                        </Td>
                                        <Td key={`${idx}_desc`}><div>
                                            <div>{p.description}</div>
                                            {p.defaultValue && p.defaultValue.toString().length > 0 && <div>{"Default value: " + p.defaultValue}</div>}
                                        </div></Td>
                                        <Td key={`${idx}_type`}>{p.type}</Td>
                                        <Td key={`${idx}_label`}>{p.label}</Td>
                                    </Tr>
                                ))}
                            </Tbody>
                        </TableComposable>
                    </div>
                    }
                </Flex>
            </Modal>
        )
    }
}
