/* global document */

import moment from 'moment';
import React from 'react';
import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import PropTypes from 'prop-types';
import withHandlers from 'recompose/withHandlers';
import onlyUpdateForKeys from 'recompose/onlyUpdateForKeys';
import styled from 'styled-components';
import { tint } from 'polished';

import * as colors from '@descarteslabs/pizzazz/styles/colors';
import * as shadows from '@descarteslabs/pizzazz/styles/shadows';
import * as dimensions from '@descarteslabs/pizzazz/styles/dimensions';
import * as fonts from '@descarteslabs/pizzazz/styles/fonts';
import { flex_row, flex_col, icon_base } from '@descarteslabs/pizzazz/styles/mixins';
import ShowLayerIcon from '@descarteslabs/pizzazz/styles/icons/eye-closed.svg';
import HideLayerIcon from '@descarteslabs/pizzazz/styles/icons/eye-open.svg';
import HideOutlinesIcon from '@descarteslabs/pizzazz/styles/icons/outline-on.svg';
import ShowOutlinesIcon from '@descarteslabs/pizzazz/styles/icons/outline-off.svg';
import ActiveInspectModeIcon from '@descarteslabs/pizzazz/styles/icons/metadata-inspect-a02.svg';
import InspectModeIcon from '@descarteslabs/pizzazz/styles/icons/metadata-inspect.svg';
import ActivePBOverlayIcon from '@descarteslabs/pizzazz/styles/icons/map-labels-a02.svg';
import PBOverlayIcon from '@descarteslabs/pizzazz/styles/icons/map-labels.svg';
import DotsIcon from '@descarteslabs/pizzazz/styles/icons/dots.svg';
import TimelineAnchorIcon from '@descarteslabs/pizzazz/styles/icons/line.svg';
import ActiveTimelineAnchorIcon from '@descarteslabs/pizzazz/styles/icons/line-a02.svg';

import Button from '@descarteslabs/cycle-widgets/es2015/Button';
import LaxInput from '@descarteslabs/cycle-widgets/es2015/LaxInput';
import { TooltipTop, TooltipBottom, TooltipRight } from '@descarteslabs/cycle-widgets/es2015/Tooltips';
import { accessClass } from '@descarteslabs/cycle-widgets/es2015/utils/access';

import { stripUserHash } from '../util';

import { LatLngInput } from '@descarteslabs/react-ts-widgets';


const BUTTON_BORDER_COLOR = colors.primary.blue;
const BUTTON_COLOR = colors.fill[2];

// TODO: Refactor large view into individual components.

/* Styled components */

// Main container.
const MenuContainer = styled.div`
    ${flex_col()}
    max-width: 80vw;
    min-width: 300px;
    max-height: calc(100vh - 60px);
`;

// Icon stylings
const iconWidth = '1.5rem';
const IconNoClickContainer = styled.div`
    position: relative;
    height: inherit;
    z-index: 1;

    & svg {
        ${icon_base({ size: iconWidth, width: iconWidth })};
    }
`;
const IconContainer = IconNoClickContainer.extend`
    &:hover {
        cursor: pointer;
    }
`;

/* Map location section */

const MapCenterContainer = styled.div`
    ${flex_col({ align: 'flex-start' })}
    position: relative;
    border-bottom: 1px solid ${colors.stroke[1]};
    // flex: 1 auto;
    padding: ${dimensions.base};
    flex: 1 0 auto;
`;
const CenterContainer = styled.div`
    ${flex_row({ wrap: 'wrap' })}
    width: 100%;
`;
const CenterLabelContainer = styled.div`
    ${flex_row({ wrap: 'wrap', align: 'center' })}
`;
const LatitudeContainer = styled.div`
    ${flex_row({ wrap: 'wrap' })}
    flex: 1 auto;
    font-size: ${fonts.sizes.small};
    padding: ${dimensions.base_small};
`;
const LongitudeContainer = styled.div`
    ${flex_row({ wrap: 'wrap' })}
    flex: 1 auto;
    font-size: ${fonts.sizes.small};
    padding: ${dimensions.base_small};
`;
const CenterIconContainer = IconNoClickContainer.extend``;
const CenterLabel = styled.div`
    margin-bottom: ${dimensions.base_small};
    font-size: ${fonts.sizes.medium};
`;
const StyledLabel = styled.label`
    padding-right: ${dimensions.base_small};
    font-weight: ${fonts.weights.light};
`;
const StyledInput = styled(LaxInput)`
    line-height: 1.25rem;
    padding-left: ${dimensions.base_small};
`;

/* Layer menu section */

const LayerMenuContainer = styled.div`
    ${flex_col({ align: 'flex-start' })}
    position: relative;
    // flex: 1 auto;
    padding: ${dimensions.base};
    flex: 1 0 auto;
`;
const LayerMenuLabelContainer = styled.div`
    ${flex_row({ align: 'center' })}
    align-self: left;
`;
const LayerMenuIconContainer = IconNoClickContainer.extend``;
const LayerMenuLabel = styled.div`
    margin-bottom: ${dimensions.base_small};
    font-size: ${fonts.sizes.medium};
`;
const LayersContainer = styled.div`
    ${flex_col()}
    width: 100%;
    -webkit-transform: translateZ(0);
    z-index: 2;
`;
const LayerContainer = styled.div`
    background: ${colors.fill[1]};
    ${flex_row({ align: 'center', justify: 'space-between' })}
    flex: 1 auto;
    border-left: ${dimensions.base_small} solid ${({ color }) => color};
    ${shadows.small}
    &:hover {
        cursor: ${({ isDragging }) => (isDragging ? 'move' : 'grab')};
    }
`;
const LayerLabelContainer = styled.div`
    position: relative;
    flex: 2 1;
    padding: 1rem 0.5rem;
`;
const LayerLabelId = styled(LaxInput)`
    font-size: ${fonts.sizes.medium};
    font-weight: ${fonts.weights.normal};
    font-family: Source Sans Pro,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
    -webkit-font-smoothing: subpixel-antialiased;
    -webkit-appearance: none;
    outline: none;
    background: inherit;
    text-overflow: ellipsis;
    word-wrap: normal;
    transition: all 0.4s ease;
    padding: 0.25rem 0.5rem;
    padding-left: 0.25rem;
    margin-left: -0.25rem;
    border-radius: 2px;
    border: 1px solid transparent;

    &:hover, &:focus {
        border: 1px solid ${colors.stroke[1]};
    }
`;

const LayerLabelExtra = styled.div`
    font-size: ${fonts.sizes.small};
    font-weight: ${fonts.weights.light};
    color: ${colors.stroke[3]};
`;

// Button and icon containers
const ButtonContainer = styled.div`
    position: relative;
    text-align: center;
    width: 50%;
    padding: ${dimensions.base_small};
    align-self: center;
    & button {
        width: 100%;
        border: 1px solid ${BUTTON_BORDER_COLOR};
        color: ${BUTTON_COLOR};
        &:hover {
            border-color: ${tint(0.8, BUTTON_BORDER_COLOR)};
            color: ${tint(0.8, BUTTON_COLOR)};
        }
        &:focus {
            box-shadow: none;
        }
    }
`;
const LayerButtonsContainer = styled.div`
    ${flex_row({ wrap: 'wrap', justify: 'space-around' })}
    margin-top: ${dimensions.base_small};
    margin-right: 0.1875rem;
`;
const BaseLayerButtonContainer = styled.div`
    flex: 0 2;
    position: relative;
    padding: 0;
    margin-left: calc(${dimensions.base_small}/2);
    margin-right: calc(${dimensions.base_small}/2);
`;
const VisibilityContainer = BaseLayerButtonContainer.extend`
    margin-left: 0.5rem;
`;
const VTVisibilityContainer = BaseLayerButtonContainer.extend``;
const TimelineAnchorContainer = BaseLayerButtonContainer.extend`
    & svg {
        transform: rotate(45deg);
    }
`;
const DotsContainer = BaseLayerButtonContainer.extend``;
const LayerOptionsContainer = styled.div`
    ${flex_col()}
    background: ${colors.fill[1]};
    position: absolute;
    left: 225%;
    margin-top: -8px;
    top: 0;
    ${shadows.medium}
    width: 10rem;
`;
const BaseLayerOption = styled.div`
    text-align: center;
    white-space: nowrap;
    padding: ${dimensions.base_small};
    &:hover {
        cursor: pointer;
        background: ${colors.fill[2]};
    }
`;
const LayerOptionStaticXYZ = BaseLayerOption.extend``;
const LayerOptionEdit = BaseLayerOption.extend``;
const LayerOptionDelete = BaseLayerOption.extend``;
const ToggleButtonsContainer = styled.div`
    position: absolute;
    top: ${dimensions.base};
    right: ${dimensions.base};
    ${flex_row({ wrap: 'wrap', justify: 'space-around' })}
`;
const TogglePBOverlayContainer = styled.div`
    position: relative;
`;
const ToggleInspectionContainer = styled.div`
    position: relative;
    margin-left: ${dimensions.base_small};
`;
const DotsIconContainer = IconContainer.extend``;

// Tooltips
const MenuTooltipTop = TooltipTop.extend.attrs({
    size: 'x_small',
})``;
const MenuTooltipRight = TooltipRight.extend.attrs({
    size: 'x_small',
})``;
const MenuTooltipBottom = TooltipBottom.extend.attrs({
    size: 'x_small',
})``;
const InspectionTooltip = MenuTooltipRight.extend`
    left: 125%;
    top: -8px;

    &::after {
        margin-top: -6px;
    }
`;
const ToggleLayerTooltipTop = MenuTooltipTop.extend`
    width: 80px;
    margin-left: -40px;
`;
const OptionsTooltipTop = MenuTooltipTop.extend`
    width: 60px;
    margin-left: -30px;
`;
const AddLayerTooltip = MenuTooltipBottom.extend``;
const SliderValTop = MenuTooltipTop.extend`
    width: 80px;
    margin-left: -40px;
    left: calc(${({ value }) => value} * (6rem - 0.25rem) + 0.125rem);
    bottom: 80%;
`;

/* Opacity slider */

const Slider = styled.input`
    -webkit-appearance: none;
    -moz-appearance: none;
    background: transparent;
    width: 6rem;

    &:focus {
        outline: none;
    }

    &::-webkit-slider-thumb {
        position: relative;
        -webkit-appearance: none;
        height: 1rem;
        width: 0.25rem;
        border-radius: 0;
        background-color: ${colors.primary.blue};
        border: none;
        cursor: pointer;
        margin-top: -${dimensions.base_small};
        ${shadows.small};
    }
    &::-webkit-slider-runnable-track {
        -webkit-appearance: none;
        background: ${colors.stroke[2]};
        height: 0.25rem;
        cursor: pointer;
        width: 100%;
    }
    &::-moz-range-thumb {
        position: relative;
        -moz-appearance: none;
        height: 1rem;
        width: 0.25rem;
        border-radius: 0;
        background-color: ${colors.primary.blue};
        border: none;
        cursor: pointer;
        margin-top: -${dimensions.base_small};
        ${shadows.small};
    }
    &::-moz-range-track {
        -moz-appearance: none;
        background: ${colors.stroke[2]};
        height: 0.25rem;
        cursor: pointer;
        width: 100%;
    }
    &::-ms-thumb {
        position: relative;
        -ms-appearance: none;
        height: 1rem;
        width: 0.25rem;
        border-radius: 0;
        background-color: ${colors.primary.blue};
        border: none;
        cursor: pointer;
        margin-top: -${dimensions.base_small};
        ${shadows.small};
    }
    &::-ms-track {
        -ms-appearance: none;
        background: ${colors.stroke[2]};
        height: 0.25rem;
        cursor: pointer;
        width: 100%;
    }
    &::-ms-tooltip {
        display: none;
    }
`;
const OpacitySliderContainer = styled.div`
    ${flex_row({ align: 'center' })}
    position: relative;
    margin: 0 ${dimensions.base_small};
    padding: 1.5rem 0;
`;

const OpacitySlider = ({ index, value, onChange, onEnter, onLeave }) => {
    return (
        <OpacitySliderContainer
            onMouseEnter={onEnter}
            onMouseLeave={onLeave}
        >
            <Slider
                id={`opacity-slider-${index}`}
                type="range"
                min="0.0"
                max="1.0"
                step="0.01"
                value={value}
                onChange={onChange}
            />
            <SliderValTop
                value={value}
            >
                Opacity: {parseFloat(value).toFixed(2)}
            </SliderValTop>
        </OpacitySliderContainer>
    );
};

OpacitySlider.propTypes = {
    index: PropTypes.number.isRequired,
    value: PropTypes.number.isRequired,
    onChange: PropTypes.func.isRequired,
    onEnter: PropTypes.func.isRequired,
    onLeave: PropTypes.func.isRequired,
};

/* Layer options */

class LayerOptions extends React.Component {

    componentDidMount() {
        document.addEventListener('mousedown', this.handleClickOutside);
    }

    componentWillUnmount() {
        document.removeEventListener('mousedown', this.handleClickOutside);
    }

    setWrapperRef = node => {
        this.wrapperRef = node;
    }

    handleClickOutside = event => {
        if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
            this.props.onClickOutside();
        }
    }

    render() {
        const { onClickEdit, onClickStaticXYZ, onClickDel, onClickOutside } = this.props;
        return (
            <LayerOptionsContainer
                innerRef={this.setWrapperRef}
            >
                <LayerOptionEdit
                    onClick={e => { onClickEdit(e); return onClickOutside(); }}
                    id="edit"
                >
                    Edit Layer
                </LayerOptionEdit>
                <LayerOptionStaticXYZ
                    className={accessClass('static_xyz')}
                    onClick={e => { onClickStaticXYZ(e); return onClickOutside(); }}
                    id="static_xyz"
                >
                    Export Layer
                </LayerOptionStaticXYZ>
                <LayerOptionDelete
                    onClick={e => { onClickDel(e); return onClickOutside(); }}
                    id="delete"
                >
                    Delete Layer
                </LayerOptionDelete>
            </LayerOptionsContainer>
        );
    }
}

LayerOptions.propTypes = {
    onClickDel: PropTypes.func.isRequired,
    onClickEdit: PropTypes.func.isRequired,
    onClickOutside: PropTypes.func.isRequired,
    onClickStaticXYZ: PropTypes.func.isRequired,
};

/* Layer */

const Types = {
    LAYER: 'layer',
};

const layerSource = {
    beginDrag(props) {
        return { index: props.index };
    },
};

const layerTarget = {
    hover(props, monitor) {
        const { index: dragIndex } = monitor.getItem();
        const { index: hoverIndex } = props;

        if (dragIndex !== hoverIndex) {
            // console.log(dragIndex, hoverIndex);
            props.onMove({ dragIndex, hoverIndex });
            // props.moveLayer({ dragIndex, hoverIndex });
            monitor.getItem().index = hoverIndex; // eslint-disable-line
        }
    },
};

@DropTarget(Types.LAYER, layerTarget, connect => ({
    connectDropTarget: connect.dropTarget(),
}))
@DragSource(Types.LAYER, layerSource, (connect, monitor) => ({
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging(),
}))
class Layer extends React.Component { // eslint-disable-line
    constructor(props) {
        super(props);
        this.state = {
            overSlider: false,
        };
    }

    render() {
        const {
            connectDragSource,
            connectDropTarget,
            prodTitle,
            layer: {
                label,
                start_time,
                end_time,
                vtVisible,
                visible,
                opacity,
                color,
            },
            optionsExpanded,
            index,
            isDragging,
            timelineLayerIdx,
            onClickEdit,
            onClickDel,
            onClickToggleLayer,
            onClickToggleVT,
            onOpacityChange,
            onClickDots,
            onClickOutside,
            onClickToggleTimeline,
            onClickStaticXYZ,
            onChangeLabel,
        } = this.props;
        const element = (
            <div>
                <LayerContainer
                    color={color}
                    isDragging={isDragging}
                >
                    <VisibilityContainer
                        onClick={onClickToggleLayer}
                    >
                        <ToggleLayerTooltipTop>
                            Toggle layer
                        </ToggleLayerTooltipTop>
                        <IconContainer>
                            {visible ? <HideLayerIcon /> : <ShowLayerIcon />}
                        </IconContainer>
                    </VisibilityContainer>
                    <LayerLabelContainer>
                        <LayerLabelId
                            type="text"
                            name="LayerLabel"
                            value={label !== null ? label : prodTitle}
                            onChange={onChangeLabel}
                            className="data-hj-whitelist"
                        />
                        <LayerLabelExtra>
                            {`${moment.utc(start_time).format('YYYY-MM-DD')} - ${moment.utc(end_time).format('YYYY-MM-DD')}`}
                        </LayerLabelExtra>
                    </LayerLabelContainer>
                    <OpacitySlider
                        index={index}
                        value={opacity}
                        onChange={onOpacityChange}
                        onEnter={_ => this.setState({ overSlider: true })}
                        onLeave={_ => this.setState({ overSlider: false })}
                    />
                    <LayerButtonsContainer>
                        <VTVisibilityContainer
                            onClick={onClickToggleVT}
                        >
                            <MenuTooltipTop
                                size="x_small"
                            >
                                Toggle image outlines
                            </MenuTooltipTop>
                            <IconContainer>
                                {vtVisible ? <HideOutlinesIcon /> : <ShowOutlinesIcon />}
                            </IconContainer>
                        </VTVisibilityContainer>
                        <TimelineAnchorContainer
                            onClick={onClickToggleTimeline}
                        >
                            <MenuTooltipTop>
                                Anchor to timeline
                            </MenuTooltipTop>
                            <IconContainer>
                                {index === timelineLayerIdx ? <ActiveTimelineAnchorIcon /> : <TimelineAnchorIcon />}
                            </IconContainer>
                        </TimelineAnchorContainer>
                        <DotsContainer>
                            <OptionsTooltipTop>
                                Options
                            </OptionsTooltipTop>
                            {optionsExpanded
                                ? <LayerOptions
                                    onClickEdit={onClickEdit}
                                    onClickStaticXYZ={onClickStaticXYZ}
                                    onClickDel={onClickDel}
                                    onClickOutside={onClickOutside}
                                />
                                : null
                            }
                            <DotsIconContainer
                                onClick={onClickDots}
                            >
                                <DotsIcon />
                            </DotsIconContainer>
                        </DotsContainer>
                    </LayerButtonsContainer>
                </LayerContainer>
            </div>
        );
        return this.state.overSlider
            ? element
            : connectDragSource(connectDropTarget(element));
    }
}

const layerEnhancer = withHandlers({
    onClickEdit: ({ index, layer, onEditLayer }) => _ => onEditLayer({ index, layer }),
    onClickDel: ({ index, onRemoveLayer }) => _ => onRemoveLayer(index),
    onClickToggleLayer: ({ index, layer: { visible }, onShowLayer, onHideLayer }) => _ => (visible ? onHideLayer(index) : onShowLayer(index)),
    onClickToggleVT: ({ index, layer: { vtVisible }, onShowVT, onHideVT }) => _ => (vtVisible ? onHideVT(index) : onShowVT(index)),
    onOpacityChange: ({ index, onOpacityChange }) => e => onOpacityChange({ index, value: Number(e.target.value) }),
    onClickStaticXYZ: ({ layer, onStaticXYZ }) => e => (e.target.id === 'static_xyz' ? onStaticXYZ(layer) : void 0),
    onClickDots: ({ index, onExpandLayer }) => _ => onExpandLayer(index),
    onClickOutside: ({ onCollapseLayer }) => _ => onCollapseLayer(),
    onClickToggleTimeline: ({ index, timelineLayerIdx, onToggleTimeline }) => _ => onToggleTimeline(index === timelineLayerIdx ? -1 : index),
    onChangeLabel: ({ index, onChangeLayerLabel }) => e => onChangeLayerLabel({ index, value: e.target.value }),
});

const EnhancedLayer = layerEnhancer(Layer);

Layer.propTypes = {
    index: PropTypes.number.isRequired,
    layer: PropTypes.object.isRequired,
    optionsExpanded: PropTypes.bool.isRequired,
    prodTitle: PropTypes.string.isRequired,
    timelineLayerIdx: PropTypes.number.isRequired,
    onChangeLabel: PropTypes.func.isRequired,
    onClickDel: PropTypes.func.isRequired,
    onClickDots: PropTypes.func.isRequired,
    onClickEdit: PropTypes.func.isRequired,
    onClickOutside: PropTypes.func.isRequired,
    onClickStaticXYZ: PropTypes.func.isRequired,
    onClickToggleLayer: PropTypes.func.isRequired,
    onClickToggleTimeline: PropTypes.func.isRequired,
    onClickToggleVT: PropTypes.func.isRequired,
    onOpacityChange: PropTypes.func.isRequired,
    connectDragSource: PropTypes.func,
    connectDropTarget: PropTypes.func,
    isDragging: PropTypes.bool,
};

/* Layers */

@DragDropContext(HTML5Backend)
class Layers extends React.Component { // eslint-disable-line
    render() {
        const {
            layers,
            prodIdTitleMap,
            optionsExpanded,
            staticLayerStatus,
            timelineLayerIdx,
            onEditLayer,
            onShowLayer,
            onHideLayer,
            onRemoveLayer,
            onShowVT,
            onHideVT,
            onOpacityChange,
            onStaticXYZ,
            onExpandLayer,
            onCollapseLayer,
            onChangeLayerLabel,
            onMove,
            onToggleTimeline,
        } = this.props;
        return (
            <div>
                {layers.map((layer, index) => (
                    <EnhancedLayer
                        key={index}
                        index={index}
                        layer={layer}
                        prodTitle={prodIdTitleMap[layer.products] || stripUserHash(layer.products)}
                        optionsExpanded={optionsExpanded === index}
                        staticLayerStatus={staticLayerStatus}
                        timelineLayerIdx={timelineLayerIdx}
                        onEditLayer={onEditLayer}
                        onShowLayer={onShowLayer}
                        onHideLayer={onHideLayer}
                        onRemoveLayer={onRemoveLayer}
                        onShowVT={onShowVT}
                        onHideVT={onHideVT}
                        onOpacityChange={onOpacityChange}
                        onStaticXYZ={onStaticXYZ}
                        onExpandLayer={onExpandLayer}
                        onCollapseLayer={onCollapseLayer}
                        onChangeLayerLabel={onChangeLayerLabel}
                        onMove={onMove}
                        onToggleTimeline={onToggleTimeline}
                    />
                ))}
            </div>
        );
    }
}

const layersEnhancer = onlyUpdateForKeys([ 'layerLength', 'layers', 'prodIdTitleMap', 'optionsExpanded', 'staticLayerStatus', 'timelineLayerIdx', 'onChangeLayerLabel', 'onClickLayer', 'onCollapseLayer', 'onExpandLayer', 'onHideLayer', 'onHideVT', 'onMove', 'onOpacityChange', 'onRemoveLayer', 'onShowLayer', 'onShowVT', 'onStaticXYZ' ]);

const EnhancedLayers = layersEnhancer(Layers);

Layers.propTypes = {
    layers: PropTypes.array.isRequired,
    optionsExpanded: PropTypes.number.isRequired,
    prodIdTitleMap: PropTypes.object.isRequired,
    staticLayerStatus: PropTypes.number.isRequired,
    timelineLayerIdx: PropTypes.number.isRequired,
    onChangeLayerLabel: PropTypes.func.isRequired,
    onCollapseLayer: PropTypes.func.isRequired,
    onEditLayer: PropTypes.func.isRequired,
    onExpandLayer: PropTypes.func.isRequired,
    onHideLayer: PropTypes.func.isRequired,
    onHideVT: PropTypes.func.isRequired,
    onMove: PropTypes.func.isRequired,
    onOpacityChange: PropTypes.func.isRequired,
    onRemoveLayer: PropTypes.func.isRequired,
    onShowLayer: PropTypes.func.isRequired,
    onShowVT: PropTypes.func.isRequired,
    onStaticXYZ: PropTypes.func.isRequired,
    onToggleTimeline: PropTypes.func.isRequired,
};

/* View */

const MenuView = ({
    inspecting, labelsTop, optionsExpanded, layers, lat, lon, staticLayerStatus,
    timelineLayerIdx, prodIdTitleMap,
    onEditLayer, onAddLayer, onShowLayer, onHideLayer, onRemoveLayer, onShowVT, onHideVT,
    onChangeLatitude, onChangeLongitude, onChangeLayerLabel, onTogglePBOverlay, onToggleInspection,
    onOpacityChange, onStaticXYZ, onExpandLayer, onCollapseLayer, onMove, onToggleTimeline,
}) => (
    <MenuContainer>
        <MapCenterContainer>
            <CenterLabelContainer>
                <CenterLabel>
                  Latitude, Longitude
                </CenterLabel>
            </CenterLabelContainer>
            <CenterContainer>
                <LatLngInput
                    position={[lon, lat]}
                    onChangeLatitude={onChangeLatitude}
                    onChangeLongitude={onChangeLongitude}
                />
            </CenterContainer>
        </MapCenterContainer>
        <LayerMenuContainer>
            <LayerMenuLabelContainer>
                <LayerMenuLabel>
                    Layers
                </LayerMenuLabel>
            </LayerMenuLabelContainer>
            <LayersContainer>
                <EnhancedLayers
                    layers={layers}
                    prodIdTitleMap={prodIdTitleMap}
                    optionsExpanded={optionsExpanded}
                    staticLayerStatus={staticLayerStatus}
                    timelineLayerIdx={timelineLayerIdx}
                    onEditLayer={onEditLayer}
                    onShowLayer={onShowLayer}
                    onHideLayer={onHideLayer}
                    onRemoveLayer={onRemoveLayer}
                    onShowVT={onShowVT}
                    onHideVT={onHideVT}
                    onOpacityChange={onOpacityChange}
                    onStaticXYZ={onStaticXYZ}
                    onExpandLayer={onExpandLayer}
                    onCollapseLayer={onCollapseLayer}
                    onChangeLayerLabel={onChangeLayerLabel}
                    onMove={onMove}
                    onToggleTimeline={onToggleTimeline}
                />
            </LayersContainer>
            <ButtonContainer>
                <AddLayerTooltip>
                    Add a new layer to the map
                </AddLayerTooltip>
                <Button
                    name="add-layer-button"
                    displayStyle="primary"
                    size="medium"
                    onClick={onAddLayer}
                >
                    Add Layer
                </Button>
            </ButtonContainer>
            <ToggleButtonsContainer>
                <TogglePBOverlayContainer
                    onClick={onTogglePBOverlay}
                >
                    <InspectionTooltip>
                        Toggle placenames and boundaries
                    </InspectionTooltip>
                    <IconContainer>
                        {labelsTop ? <ActivePBOverlayIcon /> : <PBOverlayIcon />}
                    </IconContainer>
                </TogglePBOverlayContainer>
                <ToggleInspectionContainer
                    onClick={onToggleInspection}
                >
                    <InspectionTooltip>
                        Inspect metadata of a selected feature
                    </InspectionTooltip>
                    <IconContainer>
                        {inspecting ? <ActiveInspectModeIcon /> : <InspectModeIcon />}
                    </IconContainer>
                </ToggleInspectionContainer>
            </ToggleButtonsContainer>
        </LayerMenuContainer>
    </MenuContainer>
);

MenuView.propTypes = {
    inspecting: PropTypes.bool.isRequired,
    labelsTop: PropTypes.bool.isRequired,
    lat: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]).isRequired,
    layers: PropTypes.array.isRequired,
    lon: PropTypes.oneOfType([
        PropTypes.number,
        PropTypes.string,
    ]).isRequired,
    optionsExpanded: PropTypes.number.isRequired,
    prodIdTitleMap: PropTypes.object.isRequired,
    staticLayerStatus: PropTypes.number.isRequired,
    timelineLayerIdx: PropTypes.number.isRequired,
    onAddLayer: PropTypes.func.isRequired,
    onChangeLatitude: PropTypes.func.isRequired,
    onChangeLayerLabel: PropTypes.func.isRequired,
    onChangeLongitude: PropTypes.func.isRequired,
    onCollapseLayer: PropTypes.func.isRequired,
    onEditLayer: PropTypes.func.isRequired,
    onExpandLayer: PropTypes.func.isRequired,
    onHideLayer: PropTypes.func.isRequired,
    onHideVT: PropTypes.func.isRequired,
    onMove: PropTypes.func.isRequired,
    onOpacityChange: PropTypes.func.isRequired,
    onRemoveLayer: PropTypes.func.isRequired,
    onShowLayer: PropTypes.func.isRequired,
    onShowVT: PropTypes.func.isRequired,
    onStaticXYZ: PropTypes.func.isRequired,
    onToggleInspection: PropTypes.func.isRequired,
    onTogglePBOverlay: PropTypes.func.isRequired,
    onToggleTimeline: PropTypes.func.isRequired,
};

export default MenuView;
