import * as React from 'react';
import Srl from "../data/Srl";
import SrlAbsolute from "./SrlAbsolutePosition/SrlAbsolute";
import TokenAbsolute from "./SrlAbsolutePosition/TokenAbsolute";
import LabelAbsolute from "./SrlAbsolutePosition/LabelAbsolute";
import Frame from "../data/Frame";
import DefaultInks from "./Inks";
import TokensSelection from "./Selection/TokensSelection";
import RoleSelection from "./Selection/RoleSelection";
import {isTokenSelected, isRoleSelected} from "./Selection/isSelected";
import DragingSelection from "./Selection/DragingSelection";
import {
    LINE_HEIGHT,
    LABEL_FONT_SIZE,
    LABEL_FONT_FAMILY,
    TOKEN_FONT_SIZE,
    TRIANGLE_SIZE,
    SELECTION_BG,
    TOKEN_FONT_FAMILY
} from './LayoutConf';
import SrlVisualizerNoSelection from "./SrlVisualizerNoSelection";
import * as Styles from "./SrlVisualizerStyles";
export type Selection = null|TokensSelection|RoleSelection|DragingSelection;

type Props = {
    srl: Srl,
    noArrow?: boolean,
    inks?: typeof DefaultInks,
    onRequestSelectionChange?: (selection:Selection)=>void,
    onLayoutChange?: (layout:SrlAbsolute|null)=>void,
    selection?: Selection,
    width?: number,
};

type State = {
    srlAbsolute: null|SrlAbsolute,
    selection: Selection,
};


class SrlVisualizer extends React.PureComponent<Props,State> {
    constructor(props:Props) {
        super(props);
        this.state = {srlAbsolute: null, selection: null};
    }

    handleSelect = (selection:Selection):void => {
        if(typeof(this.props.selection)!=='undefined') {
            setTimeout(()=>this.props.onRequestSelectionChange && this.props.onRequestSelectionChange(selection),0);
        }
        else {
            this.setState({selection:selection});
        }
    };

    getSelection ():null|Selection {
        if(typeof(this.props.selection) === 'undefined') return this.state.selection;
        return this.props.selection;
    }

    handleLayoutChange = (srlAbsolute:null|SrlAbsolute)=> {
        this.setState({srlAbsolute});
        setTimeout(()=>this.props.onLayoutChange && this.props.onLayoutChange(srlAbsolute),0);
    };

    componentWillReceiveProps(newProps:Props) {
        if(newProps.srl === this.props.srl && newProps.noArrow === this.props.noArrow) return;
        this.setState({srlAbsolute: null});
    }

    render() {
        const {srl, noArrow, inks, width} = this.props;
        return <div className={Styles.relative}>
            <SrlVisualizerNoSelection srl={srl} inks={inks} noArrow={noArrow} width={width}
                                       onLayoutChange={this.handleLayoutChange}
                                       onRequestSelectionChange={this.handleSelect}
            />
            {this.renderSvg()}
        </div>
    }
    renderSvg() {
        const srlAbsolute = this.state.srlAbsolute;
        if(srlAbsolute == null) return;
        return <svg width={srlAbsolute.width} height={srlAbsolute.height} style={{position:'absolute',left:0,top:0,pointerEvents:'none',display:'block'}} >
            {this.renderSvgTokens(srlAbsolute.tokens)}
            {this.renderSvgLabels(srlAbsolute.labels)}
        </svg>
    }
    renderSvgTokens(tokenAbsolutes:TokenAbsolute[]) {
        const tokenStrs:string[] = this.props.srl.tokens;
        return tokenAbsolutes.map(token=>{
            const commonTextStyle = {
                x:token.x, y:token.y+token.h, fontSize:TOKEN_FONT_SIZE, fontFamily:TOKEN_FONT_FAMILY

            };
            if(isTokenSelected(this.getSelection(), token.index, this.props.srl.frames)) {
                return <g key={token.index}>
                    <rect x={token.x-2} y={token.y} width={token.w+4} height={TOKEN_FONT_SIZE*LINE_HEIGHT} fill={SELECTION_BG}/>
                    <text fill="white" {...commonTextStyle}>{tokenStrs[token.index]}</text>
                </g>
            }
            return null;
        })
    }
    renderSvgLabels(labelAbsolutes:LabelAbsolute[]) {
        const frames:Frame[] = this.props.srl.frames;
        return labelAbsolutes.map(label=>{
            const key = `${label.frameIndex},${label.roleIndex},${label.labelIndex}`;
            const commonTextStyle = {x:label.x,y:label.y+label.h,fontSize:LABEL_FONT_SIZE,fontFamily:LABEL_FONT_FAMILY};
            const textContent = frames[label.frameIndex].roles[label.roleIndex].name;
            if(isRoleSelected(this.getSelection(), label.frameIndex, label.roleIndex)) {
                return <g key={key}>
                    <rect x={label.x-2} y={label.y} width={label.w+4} height={LABEL_FONT_SIZE*LINE_HEIGHT} fill={SELECTION_BG}/>
                    <text {...commonTextStyle} fill="white">{textContent}</text>
                </g>
            }
            return null;
        })
    }
}

export default SrlVisualizer;