/*
 * Copyright 2019 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed 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 * as React from 'react';

import {
    Button,
    Chip,
    ChipGroup,
    ChipGroupToolbarItem,
    Form,
    FormGroup,
    Gallery,
    GalleryItem,
    Modal,
    Stack,
    StackItem,
    TextInput
} from '@patternfly/react-core';

import { AccountServiceContext } from '../../account-service/AccountServiceContext';
import { Resource, Permission, Scope } from './resource-model';
import { Msg } from '../../widgets/Msg';
import {ContentAlert} from '../ContentAlert';
import { PermissionSelect } from './PermissionSelect';

interface ShareTheResourceProps {
    resource: Resource;
    permissions: Permission[];
    sharedWithUsersMsg: React.ReactNode;
    onClose: () => void;
    children: (toggle: () => void) => void;
}

interface ShareTheResourceState {
    isOpen: boolean;
    permissionsSelected: Scope[];
    permissionsUnSelected: Scope[];
    usernames: string[];
    usernameInput: string;
}

/**
 * @author Stan Silvert ssilvert@redhat.com (C) 2019 Red Hat Inc.
 */
export class ShareTheResource extends React.Component<ShareTheResourceProps, ShareTheResourceState> {
    protected static defaultProps = {permissions: []};
    static contextType = AccountServiceContext;
    context: React.ContextType<typeof AccountServiceContext>;

    public constructor(props: ShareTheResourceProps, context: React.ContextType<typeof AccountServiceContext>) {
        super(props);
        this.context = context;
    
        this.state = {
            isOpen: false,
            permissionsSelected: [],
            permissionsUnSelected: this.props.resource.scopes,
            usernames: [],
            usernameInput: ''
        };
    }

    private clearState(): void {
        this.setState({
            permissionsSelected: [],
            permissionsUnSelected: this.props.resource.scopes,
            usernames: [],
            usernameInput: ''
        });
    }

    private handleAddPermission = () => {
        const rscId: string = this.props.resource._id;
        const newPermissions: string[] = [];

        for (const permission of this.state.permissionsSelected) {
            newPermissions.push(permission.name);
        }

        const permissions = [];

        for (const username of this.state.usernames) {
            permissions.push({username: username, scopes: newPermissions});
        }

        this.handleToggleDialog();

        this.context!.doPut(`/resources/${rscId}/permissions`, permissions)
            .then(() => {
                ContentAlert.success('shareSuccess');
                this.props.onClose();
            })
    };

    private handleToggleDialog = () => {
       if (this.state.isOpen) {
           this.setState({isOpen: false});
           this.props.onClose();
       } else {
           this.clearState();
           this.setState({isOpen: true});
       }
    };

    private handleUsernameChange = (username: string) => {
        this.setState({usernameInput: username});
    }

    private handleAddUsername = async () => {
        if ((this.state.usernameInput !== '') && (!this.state.usernames.includes(this.state.usernameInput))) {
            const response = await this.context!.doGet<{username: string}>(`/resources/${this.props.resource._id}/user`, { params: { value: this.state.usernameInput } });
            if (response.data && response.data.username) {
                this.setState({ usernameInput: '', usernames: [...this.state.usernames, this.state.usernameInput] });
            } else {
                ContentAlert.info('userNotFound', [this.state.usernameInput]);
            }
        }
    }

    private handleEnterKeyInAddField = (event: React.KeyboardEvent) => {
        if (event.key === "Enter") {
            event.preventDefault();
            this.handleAddUsername();
        }
    }

    private handleDeleteUsername = (username: string) => {
        const newUsernames: string[] = this.state.usernames.filter(user => user !== username);
        this.setState({usernames: newUsernames});
    }

    private isAddDisabled(): boolean {
        return this.state.usernameInput === '' || this.isAlreadyShared();
    }

    private isAlreadyShared(): boolean {
        for (let permission of this.props.permissions) {
            if (permission.username === this.state.usernameInput) return true;
        }

        return false;
    }

    private isFormInvalid(): boolean {
        return (this.state.usernames.length === 0) || (this.state.permissionsSelected.length === 0);
    }

    public render(): React.ReactNode {
        return (
            <React.Fragment>
                {this.props.children(this.handleToggleDialog)}

                <Modal
                title={'Share the resource - ' + this.props.resource.name}
                isLarge={true}
                isOpen={this.state.isOpen}
                onClose={this.handleToggleDialog}
                actions={[
                    <Button key="cancel" variant="link" onClick={this.handleToggleDialog}>
                        <Msg msgKey='cancel'/>
                    </Button>,
                    <Button key="confirm" variant="primary" id="done" onClick={this.handleAddPermission} isDisabled={this.isFormInvalid()}>
                        <Msg msgKey='done'/>
                    </Button>
                ]}
                >
                    <Stack gutter='md'>
                        <StackItem isFilled>
                        <Form>
                            <FormGroup
                                label="Add users to share your resource with"
                                type="string"
                                helperTextInvalid={Msg.localize('resourceAlreadyShared')}
                                fieldId="username"
                                isRequired
                                isValid={!this.isAlreadyShared()}
                                >
                                    <Gallery gutter='sm'>
                                        <GalleryItem>
                                            <TextInput
                                                value={this.state.usernameInput}
                                                isValid={!this.isAlreadyShared()}
                                                id="username"
                                                aria-describedby="username-helper"
                                                placeholder="Username or email"
                                                onChange={this.handleUsernameChange}
                                                onKeyPress={this.handleEnterKeyInAddField}
                                            />
                                        </GalleryItem>
                                        <GalleryItem>
                                            <Button key="add-user" variant="primary" id="add" onClick={this.handleAddUsername} isDisabled={this.isAddDisabled()}>
                                                <Msg msgKey="add"/>
                                            </Button>
                                        </GalleryItem>

                                </Gallery>
                                <ChipGroup withToolbar>
                                    <ChipGroupToolbarItem key='users-selected' categoryName='Share with '>
                                    {this.state.usernames.map((currentChip: string) => (
                                        <Chip key={currentChip} onClick={() => this.handleDeleteUsername(currentChip)}>
                                            {currentChip}
                                        </Chip>
                                    ))}
                                    </ChipGroupToolbarItem>
                                </ChipGroup>
                            </FormGroup>
                            <FormGroup
                                label=""
                                fieldId="permissions-selected"
                            >
                                <PermissionSelect
                                    scopes={this.state.permissionsUnSelected}
                                    onSelect={selection => this.setState({ permissionsSelected: selection })}
                                    direction="up"
                                />
                            </FormGroup>
                        </Form>
                    </StackItem>
                    <StackItem isFilled><br/></StackItem>
                    <StackItem isFilled>
                        {this.props.sharedWithUsersMsg}
                    </StackItem>

                    </Stack>
                </Modal>
            </React.Fragment>
        );
    }
}