/* global APP_HOSTNAME */
import React from 'react'
import PropTypes from 'prop-types'

import Form from 'react-toolkit/form'
import inputNames from 'common-fe/constants/input-names'
import investmentApproaches from 'common-fe/constants/investment-approaches'
import FormError from 'common-fe/utils/form-error'
import {sparsifyObj} from 'common-fe/utils'
import {copyToClipboard, isESHost} from 'common-fe/utils/browser'
import toastTypes from 'containers/toast-manager/toast-types'
import routes from 'global/constants/routes'

import Button from 'react-uikit/button'
import {Flex} from 'react-uikit/layout'
import Icon from 'react-uikit/icon'
import InvestmentApproachInput from 'components/investment-approach-input'
import TextInput from 'react-uikit/input-text'
import TextArea from 'react-uikit/textarea'
import Switch from 'react-uikit/switch'
import Toggle from 'react-uikit/switch/templates/toggle'

import BEMModule from 'utils/bem'
import styles from './styles.scss'
const bem = new BEMModule(styles)

class PortfolioSettingsForm extends React.Component {
    static formName = 'portfolio-settings'

    static defaultState = {
        data: {
            [inputNames.NAME]: '',
            [inputNames.DESCRIPTION]: '',
            [inputNames.INVESTMENT_APPROACH]: 'NONE',
            [inputNames.PORTFOLIO_IS_PUBLIC]: false,
        },
        error: {},
    }

    form = React.createRef()

    get initialState() {
        const {
            description,
            name,
            investmentApproach,
            isPublic,
        } = this.props.portfolio

        return {
            data: {
                [inputNames.NAME]:
                    name ||
                    PortfolioSettingsForm.defaultState.data[inputNames.NAME],
                [inputNames.DESCRIPTION]:
                    description ||
                    PortfolioSettingsForm.defaultState.data[
                        inputNames.DESCRIPTION
                    ],
                [inputNames.INVESTMENT_APPROACH]:
                    investmentApproach ||
                    PortfolioSettingsForm.defaultState.data[
                        inputNames.INVESTMENT_APPROACH
                    ],
                [inputNames.PORTFOLIO_IS_PUBLIC]:
                    isPublic ||
                    PortfolioSettingsForm.defaultState.data[
                        inputNames.PORTFOLIO_IS_PUBLIC
                    ],
            },
            error: {...PortfolioSettingsForm.defaultState.error},
        }
    }

    get portfolioLinkText() {
        const baseUrl = isESHost() ? APP_HOSTNAME : window.location.host
        return `${baseUrl}${routes.PORTFOLIO_SHOWCASE}/${this.props.portfolio.id}`
    }

    change = ({name, value}) => {
        this.props.onChange && this.props.onChange({[name]: value})
    }

    copy = () => {
        copyToClipboard(this.portfolioLinkText)
        this.props.showToast?.({type: toastTypes.COPIED_TO_CLIPBOARD})
    }

    updatePortfolio = (data) => {
        const {onError, onSubmit, portfolio, updatePortfolio} = this.props

        if (!updatePortfolio) {
            return
        }

        const payload = sparsifyObj({
            portfolioId: portfolio.id,
            [inputNames.NAME]: data[inputNames.NAME],
            [inputNames.DESCRIPTION]: data[inputNames.DESCRIPTION],
            [inputNames.INVESTMENT_APPROACH]:
                investmentApproaches[data[inputNames.INVESTMENT_APPROACH]]
                    .value,
            [inputNames.PORTFOLIO_IS_PUBLIC]:
                data[inputNames.PORTFOLIO_IS_PUBLIC],
        })

        updatePortfolio(payload)
            .then(() => onSubmit && onSubmit(payload))
            .catch((err) => {
                if (!err.inlineErrors || !err.inlineErrors.length || !onError) {
                    return
                }

                const error = new FormError(
                    Object.keys(PortfolioSettingsForm.defaultState.data),
                    err.inlineErrors
                )

                onError && onError(error)
            })
    }

    render() {
        const {
            data,
            error,
            portfolio: {isCoursePortfolio},
            validateOnUpdate,
            onError,
        } = this.props

        const nameClassNames = bem.classNames('c-portfolio-settings__name')
        const nameInputClassNames = bem.classNames(
            'c-portfolio-settings__name-input'
        )
        const publicPortfolioClassNames = bem.classNames(
            'c-portfolio-settings__public-portfolio'
        )
        const toggleTextClassNames = bem.classNames(
            'c-portfolio-settings__toggle-text'
        )
        const switchClassNames = bem.classNames(
            'c-portfolio-settings__switch',
            {
                hidden: isCoursePortfolio,
            }
        )
        const copyButtonClassNames = bem.classNames(
            'c-portfolio-settings__copy-button',
            {
                disabled: !data[inputNames.PORTFOLIO_IS_PUBLIC],
            }
        )
        const copyTextClassNames = bem.classNames(
            'c-portfolio-settings__copy-text',
            {
                disabled: !data[inputNames.PORTFOLIO_IS_PUBLIC],
            }
        )
        const copyIconClassNames = bem.classNames(
            'c-portfolio-settings__copy-icon'
        )
        const descriptionClassNames = bem.classNames(
            'c-portfolio-settings__description'
        )
        const approachClassNames = bem.classNames(
            'c-portfolio-settings__approach'
        )
        const hrClassNames = bem.classNames('c-portfolio-settings__hr')
        const labelClassNames = bem.classNames('c-portfolio-settings__label')
        const createButtonClassName = bem.classNames(
            'c-portfolio-settings__button'
        )
        const helpClassNames = bem.classNames('c-portfolio-settings__help')

        return (
            <Form
                data={data}
                error={error}
                name={PortfolioSettingsForm.formName}
                submitOnEnter={false}
                validateOnUpdate={validateOnUpdate}
                onChange={this.change}
                onError={onError}
                onSubmit={this.updatePortfolio}
            >
                <section className={nameClassNames}>
                    <label htmlFor={inputNames.NAME}>Portfolio Name</label>

                    <Form.Field
                        className={nameInputClassNames}
                        component={TextInput.Alternate}
                        maxLength={30}
                        name={inputNames.NAME}
                        required
                    />
                </section>

                <section className={publicPortfolioClassNames}>
                    <Flex justify="space-between">
                        <label className={labelClassNames}>
                            {isCoursePortfolio ? (
                                'Public portfolio link'
                            ) : (
                                <React.Fragment>
                                    Make portfolio&nbsp;
                                    <button
                                        className={toggleTextClassNames}
                                        onClick={() =>
                                            this.change({
                                                name:
                                                    inputNames.PORTFOLIO_IS_PUBLIC,
                                                value: !data[
                                                    inputNames
                                                        .PORTFOLIO_IS_PUBLIC
                                                ],
                                            })
                                        }
                                    >
                                        {data[inputNames.PORTFOLIO_IS_PUBLIC]
                                            ? 'private'
                                            : 'public'}
                                    </button>
                                </React.Fragment>
                            )}
                        </label>

                        <Form.Field
                            className={switchClassNames}
                            component={Switch}
                            name={inputNames.PORTFOLIO_IS_PUBLIC}
                            on={data[inputNames.PORTFOLIO_IS_PUBLIC]}
                            render={Toggle}
                        />
                    </Flex>

                    <Flex align="center">
                        <Button
                            className={copyButtonClassNames}
                            disabled={!data[inputNames.PORTFOLIO_IS_PUBLIC]}
                            title="Copy"
                            onClick={this.copy}
                        >
                            &emsp;
                            <Icon className={copyIconClassNames} name="copy" />
                            <span>&nbsp;COPY&emsp;</span>
                        </Button>
                        <span className={copyTextClassNames}>
                            {this.portfolioLinkText}
                        </span>
                    </Flex>

                    <p className={helpClassNames}>
                        <a
                            href="https://learn.equitysim.com/en/articles/2795524-what-are-public-portfolios"
                            target="_blank"
                            rel="noreferrer noopener"
                        >
                            Who can see my portfolio?
                        </a>
                    </p>
                </section>

                <hr className={hrClassNames} />

                <section className={approachClassNames}>
                    <div>
                        <label
                            className={labelClassNames}
                            htmlFor={inputNames.INVESTMENT_APPROACH}
                        >
                            Investment Approach
                        </label>
                        <Form.Field
                            component={InvestmentApproachInput}
                            name={inputNames.INVESTMENT_APPROACH}
                            required
                        />
                    </div>
                </section>
                <section className={descriptionClassNames}>
                    <label htmlFor={inputNames.DESCRIPTION}>Description</label>
                    <Form.Field
                        component={TextArea}
                        maxLength={500}
                        name={inputNames.DESCRIPTION}
                        placeholder="More about your portfolio’s purpose and approach"
                        resize
                    />
                </section>
                <Form.SubmitTrigger
                    render={({submit}) => (
                        <Button
                            className={createButtonClassName}
                            variant="primary"
                            text="Save"
                            onClick={submit}
                        />
                    )}
                />
            </Form>
        )
    }
}

PortfolioSettingsForm.propTypes = {
    data: PropTypes.shape({
        [inputNames.NAME]: PropTypes.string,
        [inputNames.FUNDING_AMOUNT]: PropTypes.object,
        [inputNames.INVESTMENT_APPROACH]: PropTypes.string,
        [inputNames.DESCRIPTION]: PropTypes.string,
    }),
    error: PropTypes.shape({
        [inputNames.NAME]: PropTypes.string,
        [inputNames.FUNDING_AMOUNT]: PropTypes.string,
        [inputNames.INVESTMENT_APPROACH]: PropTypes.string,
        [inputNames.DESCRIPTION]: PropTypes.string,
    }),
    portfolio: PropTypes.object,
    showToast: PropTypes.func,
    updatePortfolio: PropTypes.func,
    validateOnUpdate: PropTypes.bool,
    onChange: PropTypes.func,
    onError: PropTypes.func,
    onSubmit: PropTypes.func,
}

PortfolioSettingsForm.defaultProps = {
    data: {...PortfolioSettingsForm.defaultState.data},
    error: {...PortfolioSettingsForm.defaultState.error},
    validateOnUpdate: true,
}

export default PortfolioSettingsForm
