/* global document */

import React from 'react';
import PropTypes from 'prop-types';
import ReactCodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/pastel-on-dark.css';
import 'codemirror/mode/javascript/javascript';
import { tint } from 'polished';
import styled, { css } from 'styled-components';

import * as colors from '@descarteslabs/pizzazz/styles/colors';
import * as dimensions from '@descarteslabs/pizzazz/styles/dimensions';
import { flex_row, flex_col, icon_base } from '@descarteslabs/pizzazz/styles/mixins';
import PolygonIcon from '@descarteslabs/pizzazz/styles/icons/polygon.svg';
import ActivePolygonIcon from '@descarteslabs/pizzazz/styles/icons/polygon-a02.svg';
import DisabledPolygonIcon from '@descarteslabs/pizzazz/styles/icons/polygon-a01disabled.svg';
import PointIcon from '@descarteslabs/pizzazz/styles/icons/point.svg';
import ActivePointIcon from '@descarteslabs/pizzazz/styles/icons/point-a02.svg';
import DisabledPointIcon from '@descarteslabs/pizzazz/styles/icons/point-a01disabled.svg';
import BoxIcon from '@descarteslabs/pizzazz/styles/icons/square.svg';
import ActiveBoxIcon from '@descarteslabs/pizzazz/styles/icons/square-a02.svg';
import DisabledBoxIcon from '@descarteslabs/pizzazz/styles/icons/square-a01disabled.svg';
import LineIcon from '@descarteslabs/pizzazz/styles/icons/line.svg';
import ActiveLineIcon from '@descarteslabs/pizzazz/styles/icons/line-a02.svg';
import DisabledLineIcon from '@descarteslabs/pizzazz/styles/icons/line-a01disabled.svg';
import ModifyIcon from '@descarteslabs/pizzazz/styles/icons/edit.svg';
import ActiveModifyIcon from '@descarteslabs/pizzazz/styles/icons/edit-a02.svg';
import DisabledModifyIcon from '@descarteslabs/pizzazz/styles/icons/edit-a01disabled.svg';
import TranslateIcon from '@descarteslabs/pizzazz/styles/icons/move.svg';
import ActiveTranslateIcon from '@descarteslabs/pizzazz/styles/icons/move-a02.svg';
import DisabledTranslateIcon from '@descarteslabs/pizzazz/styles/icons/move-a01disabled.svg';
import SelectAllIcon from '@descarteslabs/pizzazz/styles/icons/select-all.svg';
// import ActiveSelectAllIcon from '@descarteslabs/pizzazz/styles/icons/select-all-a02.svg';
import DisabledSelectAllIcon from '@descarteslabs/pizzazz/styles/icons/select-all-a01disabled.svg';
import MetadataIcon from '@descarteslabs/pizzazz/styles/icons/metadata-add-a01.svg';
import ActiveMetadataIcon from '@descarteslabs/pizzazz/styles/icons/metadata-add-a02.svg';
import DisabledMetadataIcon from '@descarteslabs/pizzazz/styles/icons/metadata-add-a01disabled.svg';
import DownloadIcon from '@descarteslabs/pizzazz/styles/icons/download-s.svg';
// import ActiveDownloadIcon from '@descarteslabs/pizzazz/styles/icons/download-s-a02.svg';
import DisabledDownloadIcon from '@descarteslabs/pizzazz/styles/icons/download-s-a01disabled.svg';
import UploadIcon from '@descarteslabs/pizzazz/styles/icons/upload-s.svg';
// import ActiveUploadIcon from '@descarteslabs/pizzazz/styles/icons/upload-s-a02.svg';
import DisabledUploadIcon from '@descarteslabs/pizzazz/styles/icons/upload-s-a01disabled.svg';
// import HideLayerIcon from '@descarteslabs/pizzazz/styles/icons/eye-open.svg';
// import ShowLayerIcon from '@descarteslabs/pizzazz/styles/icons/eye-closed.svg';
import DeleteIcon from '@descarteslabs/pizzazz/styles/icons/delete.svg';
// import ActiveDeleteIcon from '@descarteslabs/pizzazz/styles/icons/delete-a02.svg';
import DisabledDeleteIcon from '@descarteslabs/pizzazz/styles/icons/delete-a01disabled.svg';
import Button from '@descarteslabs/cycle-widgets/es2015/Button';
import { TooltipLeft } from '@descarteslabs/cycle-widgets/es2015/Tooltips';

import jsonlint from '../util/jsonlint';
import '../styles/error-marker.css';

// TODO: Refactor large view into individual components.
const BUTTON_BORDER_COLOR = colors.white;
const BUTTON_COLOR = colors.primary.dark;
const SECONDARY_BUTTON_BORDER_COLOR = colors.white;
const SECONDARY_BUTTON_COLOR = colors.white;

const iconContainerWidth = dimensions.medium;
const iconWidth = dimensions.x_small;

const IconContainer = styled.div`
    position: relative;
    width: ${iconContainerWidth};
    z-index: 1;
    padding: ${dimensions.base_small};

    ${({ disabled }) => (disabled
        ? 'cursor: default;'
        : css`
            &:hover {
                background-color: ${colors.fill[3]};
                cursor: pointer;
            }
        `
    )}

    & svg {
        ${icon_base({ size: iconWidth, width: iconWidth })};
    }
`;
const PolygonIconContainer = IconContainer.extend``;
const PointIconContainer = IconContainer.extend``;
const BoxIconContainer = IconContainer.extend``;
const LineIconContainer = IconContainer.extend`
    border-bottom: 2px solid ${colors.stroke[0]};
`;
const ModifyIconContainer = IconContainer.extend``;
const TranslateIconContainer = IconContainer.extend``;
const SelectAllIconContainer = IconContainer.extend`
    border-bottom: 2px solid ${colors.stroke[0]};
`;
const MetadataIconContainer = IconContainer.extend``;
const DownloadIconContainer = IconContainer.extend``;
const UploadIconContainer = IconContainer.extend`
    border-bottom: 2px solid ${colors.stroke[0]};
`;
const ToggleIconContainer = IconContainer.extend`
    border-top-left-radius: 5px;
    border-top-right-radius: 5px;
    ${({ collapsed }) => (collapsed
        ? css`
            border-bottom-left-radius: 3px;
            border-bottom-right-radius: 3px;
        ` : ''
    )}
    border-bottom: 2px solid ${colors.stroke[0]};
`;
const DeleteIconContainer = IconContainer.extend`
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
`;

const ToolbarContainer = styled.div`
    ${flex_col({ wrap: 'wrap' })}
`;
const ToolbarButtonsContainer = styled.div`
    ${flex_col({ wrap: 'nowrap' })}
    transition: height 0.25s;
    height: ${({ expanded }) => (expanded ? '468px' : '0')};
    overflow: ${({ _overflow }) => (_overflow
        ? 'initial'
        : 'hidden'
    )};
`;
const MetadataEditWrapper = styled.div`
    position: relative;
`;
const EditMetadataContainer = styled.div`
    display: flex;
    flex-flow: column nowrap;
    position: absolute;
    top: 0;
    right: 2.625rem;
    z-index: 2;
    ${flex_col()}

    &::after {
        content: " ";
        position: absolute;
        top: 1rem;
        left: 100%;
        margin-top: -5px;
        border-width: 7.5px;
        border-style: solid;
        border-color: transparent transparent transparent ${colors.primary.dark};
    }
`;
const EditMetadataHeader = styled.div`
    background-color: ${colors.secondary.dark};
    color: ${colors.white};
    text-align: center;
`;
const StyledReactCodeMirror = styled(ReactCodeMirror)`
    & > .CodeMirror {
        width: 300px;
        height: 188px;
    }
`;
const EditMetadataButtonsContainer = styled.div`
    ${flex_row({ justify: 'center' })}
    background-color: ${colors.secondary.dark};
    border-radius: 0 0 3px 3px;
    padding: 0.5rem;
`;
const ButtonContainer = styled.div`
    position: relative;
    text-align: center;
    align-self: center;

    & button {
        width: 100%;

        &:focus {
            box-shadow: none;
        }
    }
`;
const SaveMetadataButtonContainer = ButtonContainer.extend`
    margin-right: ${dimensions.base};

    & button {
        border: 1px solid ${BUTTON_BORDER_COLOR};
        color: ${BUTTON_COLOR};
        background-color: ${BUTTON_BORDER_COLOR};
        width: 4rem;

        &:hover {
            border-color: ${tint(0.8, BUTTON_BORDER_COLOR)};
            background-color: ${tint(0.8, BUTTON_BORDER_COLOR)};
            color: ${tint(0.8, BUTTON_COLOR)};
        }
    }
`;
const CancelMetadataButtonContainer = ButtonContainer.extend`
    & button {
        width: 4rem;
        border: 1px solid ${SECONDARY_BUTTON_BORDER_COLOR};
        color: ${SECONDARY_BUTTON_COLOR};
        &:hover {
            border-color: ${tint(0.8, SECONDARY_BUTTON_BORDER_COLOR)};
            color: ${tint(0.8, SECONDARY_BUTTON_COLOR)};
        }
    }
`;
const IconTooltip = TooltipLeft.extend
    .attrs({ size: 'small' })`
        right: 105%;
        top: 0.125rem;

        &::after {
            top: 1rem;
        }
    `;
const SwitchLabel = styled.label`
    position: relative;
    display: inline-block;
    width: 1.75rem;
    height: 1rem;
    margin-left: -0.1875rem;
    margin-bottom: -0.15rem;

    & input {
        display: none;
    }

    & input:checked + span {
        background-color: ${colors.primary.blue};
    }
    & input:checked + span:before {
        transform: translateX(0.985rem);
    }
    & input:focus + span {
        box-shadow: 0 0 1px ${colors.primary.blue};
    }

    & span {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        transition: .2s;
        border-radius: 1rem;

        &:before {
            position: absolute;
            content: "";
            height: 0.75rem;
            width: 0.75rem;
            bottom: 0.125rem;
            left: 0.015rem;
            background-color: white;
            transition: .2s;
            border-radius: 50%;
        }
    }
`;
const SwitchTooltip = IconTooltip.extend`
    right: 120%;
`;

class ToolbarView extends React.Component {
    codeMirrorRefHandler = ref => { this.codeMirror = ref; }

    codeMirrorChangeHandler = value => {
        const codeMirror = this.codeMirror.getCodeMirror();
        codeMirror.clearGutter('error');
        let metadata = null;

        try {
            metadata = jsonlint.parse(value);
        } catch (e) {
            const match = e.message.match(/line (\d+)/);
            if (match && match[1]) {
                const errElement = document.createElement('div');
                errElement.setAttribute('class', 'error-marker');
                errElement.setAttribute('message', e.message);
                codeMirror.setGutterMarker(
                    parseInt(match[1], 10) - 1, 'error', errElement
                );
            }

            return void 0;
        }

        return this.props.onChangeFeatureMetadata(metadata);
    }

    render() {
        const {
            featuresVisible,
            overflow,
            numSelectedFeatures,
            toolbarMode,
            featureCollection,
            featureMetadata,
            onCancelFeatureMetadata,
            onSaveFeatureMetadata,
            onSetDrawPolygon,
            onSetDrawPoint,
            onSetDrawBox,
            onSetDrawLine,
            onSetModify,
            onSetTranslate,
            onSelectAll,
            onEditMetadata,
            onDeleteFeatures,
            onDownloadFeatures,
            onUploadFeatures,
            onToggleFeatures,
        } = this.props;

        return (
            <ToolbarContainer>
                <ToggleIconContainer
                    key="toggle"
                    collapsed={!featuresVisible}
                >
                    <SwitchTooltip>
                        Toggle visibility of features
                    </SwitchTooltip>
                    <SwitchLabel>
                        <input
                            type="checkbox"
                            checked={featuresVisible}
                            onChange={onToggleFeatures}
                        />
                        <span />
                    </SwitchLabel>
                </ToggleIconContainer>
                <ToolbarButtonsContainer
                    expanded={featuresVisible}
                    _overflow={overflow}
                >
                    <PolygonIconContainer
                        key="polygon"
                        onClick={featuresVisible ? onSetDrawPolygon : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Draw polygon
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'polygon' ? <ActivePolygonIcon /> : <PolygonIcon />)
                            : <DisabledPolygonIcon />
                        }
                    </PolygonIconContainer>
                    <PointIconContainer
                        key="point"
                        onClick={featuresVisible ? onSetDrawPoint : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Draw point
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'point' ? <ActivePointIcon /> : <PointIcon />)
                            : <DisabledPointIcon />
                        }
                    </PointIconContainer>
                    <BoxIconContainer
                        key="box"
                        onClick={featuresVisible ? onSetDrawBox : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Draw box
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'box' ? <ActiveBoxIcon /> : <BoxIcon />)
                            : <DisabledBoxIcon />
                        }
                    </BoxIconContainer>
                    <LineIconContainer
                        key="line"
                        onClick={featuresVisible ? onSetDrawLine : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Draw line
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'line' ? <ActiveLineIcon /> : <LineIcon />)
                            : <DisabledLineIcon />
                        }
                    </LineIconContainer>
                    <ModifyIconContainer
                        key="modify"
                        onClick={featuresVisible ? onSetModify : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Modify features
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'modify' ? <ActiveModifyIcon /> : <ModifyIcon />)
                            : <DisabledModifyIcon />
                        }
                    </ModifyIconContainer>
                    <TranslateIconContainer
                        key="translate"
                        onClick={featuresVisible ? onSetTranslate : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Move features
                        </IconTooltip>
                        {featuresVisible
                            ? (toolbarMode === 'translate' ? <ActiveTranslateIcon /> : <TranslateIcon />)
                            : <DisabledTranslateIcon />
                        }
                    </TranslateIconContainer>
                    <SelectAllIconContainer
                        key="select-all"
                        onClick={featuresVisible ? onSelectAll : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Select all features
                        </IconTooltip>
                        {featuresVisible
                            ? <SelectAllIcon />
                            : <DisabledSelectAllIcon />
                        }
                    </SelectAllIconContainer>

                    <MetadataEditWrapper>
                        {toolbarMode === 'edit'
                            ? <EditMetadataContainer>
                                <EditMetadataHeader>
                                    Add Metadata
                                </EditMetadataHeader>

                                <StyledReactCodeMirror
                                    innerRef={this.codeMirrorRefHandler}
                                    onChange={this.codeMirrorChangeHandler}
                                    options={{
                                        mode: { name: 'javascript', json: true },
                                        autofocus: true,
                                        matchBrackets: true,
                                        tabSize: 2,
                                        theme: 'pastel-on-dark',
                                        lineNumbers: true,
                                        gutters: [ 'error' ],
                                    }}
                                    value={JSON.stringify(featureMetadata, null, '\t')}
                                />
                                <EditMetadataButtonsContainer>
                                    <SaveMetadataButtonContainer>
                                        <Button
                                            name="save-metadata-button"
                                            displayStyle="primary"
                                            size="medium"
                                            onClick={onSaveFeatureMetadata}
                                        >
                                            Add
                                        </Button>
                                    </SaveMetadataButtonContainer>
                                    <CancelMetadataButtonContainer>
                                        <Button
                                            name="cancel-metadata-button"
                                            displayStyle="secondaryText"
                                            size="medium"
                                            onClick={onCancelFeatureMetadata}
                                        >
                                            Cancel
                                        </Button>
                                    </CancelMetadataButtonContainer>
                                </EditMetadataButtonsContainer>
                            </EditMetadataContainer>
                            : <IconTooltip>
                                Add feature metadata
                            </IconTooltip>
                        }

                        <MetadataIconContainer
                            key="metadata"
                            onClick={featuresVisible ? onEditMetadata : null}
                            disabled={!featuresVisible}
                        >
                            {featuresVisible
                                ? (toolbarMode === 'edit' ? <ActiveMetadataIcon /> : <MetadataIcon />)
                                : <DisabledMetadataIcon />
                            }
                        </MetadataIconContainer>
                    </MetadataEditWrapper>

                    <DownloadIconContainer
                        key="download"
                        onClick={numSelectedFeatures && featuresVisible ? onDownloadFeatures : null}
                        disabled={numSelectedFeatures === 0 || !featuresVisible}
                    >
                        <IconTooltip>
                            Download selected features
                        </IconTooltip>
                        {numSelectedFeatures > 0 && featuresVisible
                            ? (
                                <a
                                    href={`data:text/json;charset=utf-8,${encodeURIComponent(featureCollection)}`}
                                    download="features.geojson"
                                >
                                    <DownloadIcon />
                                </a>
                            )
                            : (
                                <DisabledDownloadIcon />
                            )
                        }
                    </DownloadIconContainer>
                    <UploadIconContainer
                        key="upload"
                        onClick={featuresVisible ? onUploadFeatures : null}
                        disabled={!featuresVisible}
                    >
                        <IconTooltip>
                            Upload features
                        </IconTooltip>
                        {featuresVisible
                            ? <UploadIcon />
                            : <DisabledUploadIcon />
                        }
                    </UploadIconContainer>
                    <DeleteIconContainer
                        key="delete"
                        onClick={numSelectedFeatures > 0 && featuresVisible ? onDeleteFeatures : _ => void 0}
                        disabled={numSelectedFeatures === 0 || !featuresVisible}
                    >
                        <IconTooltip>
                            Delete selected features
                        </IconTooltip>
                        {numSelectedFeatures > 0 && featuresVisible ? <DeleteIcon /> : <DisabledDeleteIcon />}
                    </DeleteIconContainer>
                </ToolbarButtonsContainer>
            </ToolbarContainer>
        );
    }
}

ToolbarView.propTypes = {
    featureCollection: PropTypes.string.isRequired,
    featureMetadata: PropTypes.object.isRequired,
    featuresVisible: PropTypes.bool.isRequired,
    numSelectedFeatures: PropTypes.number.isRequired,
    overflow: PropTypes.bool.isRequired,
    toolbarMode: PropTypes.string.isRequired,
    onCancelFeatureMetadata: PropTypes.func.isRequired,
    onChangeFeatureMetadata: PropTypes.func.isRequired,
    onDeleteFeatures: PropTypes.func.isRequired,
    onDownloadFeatures: PropTypes.func.isRequired,
    onEditMetadata: PropTypes.func.isRequired,
    onSaveFeatureMetadata: PropTypes.func.isRequired,
    onSelectAll: PropTypes.func.isRequired,
    onSetDrawBox: PropTypes.func.isRequired,
    onSetDrawLine: PropTypes.func.isRequired,
    onSetDrawPoint: PropTypes.func.isRequired,
    onSetDrawPolygon: PropTypes.func.isRequired,
    onSetModify: PropTypes.func.isRequired,
    onSetTranslate: PropTypes.func.isRequired,
    onToggleFeatures: PropTypes.func.isRequired,
    onUploadFeatures: PropTypes.func.isRequired,
};

export default ToolbarView;
