import { DispBase, DispBaseT, PointI } from "./DispBase"
import { DispColor, DispTextStyle } from "@peek/peek_plugin_diagram/lookups"
import {
    PeekCanvasShapePropsContext,
    ShapeProp,
    ShapePropType
} from "../canvas/PeekCanvasShapePropsContext"
import { ModelCoordSet } from "@peek/peek_plugin_diagram/_private/tuples"

export enum TextVerticalAlign {
    top = -1,
    center = 0,
    bottom = 1
}

export enum TextHorizontalAlign {
    left = -1,
    center = 0,
    right = 1
}

export interface DispTextT extends DispBaseT {
    
    // Text Style
    fs: number;
    fsl: DispTextStyle;
    
    // Colour
    c: number;
    cl: DispColor;
    
    // Vertical Alignment
    va: number;
    
    // Horizontal Alignment
    ha: number;
    
    // Rotation
    r: number;
    
    // Text
    te: string;
    
    // Text Height (Optional)
    th: number | null;
    
    // Horizontal Stretch (default 1)
    hs: number;
    
}

export class DispText extends DispBase {
    
    static textStyle(disp: DispTextT): DispTextStyle {
        // This is set from the short id in PrivateDiagramLookupService._linkDispLookups
        return disp.fsl
    }
    
    static setTextStyle(
        disp: DispTextT,
        val: DispTextStyle
    ): void {
        // This is set from the short id in PrivateDiagramLookupService._linkDispLookups
        disp.fsl = val
        disp.fs = val == null ? null : val.id
    }
    
    static color(disp: DispTextT): DispColor {
        // This is set from the short id in PrivateDiagramLookupService._linkDispLookups
        return disp.cl
    }
    
    static setColor(
        disp: DispTextT,
        val: DispColor
    ): void {
        // This is set from the short id in PrivateDiagramLookupService._linkDispLookups
        disp.cl = val
        disp.c = val == null ? null : val.id
    }
    
    static verticalAlign(disp: DispTextT): TextVerticalAlign {
        let val = disp.va
        if (val == TextVerticalAlign.top)
            return TextVerticalAlign.top
        if (val == TextVerticalAlign.bottom)
            return TextVerticalAlign.bottom
        return TextVerticalAlign.center
    }
    
    static horizontalAlign(disp: DispTextT): TextHorizontalAlign {
        let val = disp.ha
        if (val == TextHorizontalAlign.left)
            return TextHorizontalAlign.left
        if (val == TextHorizontalAlign.right)
            return TextHorizontalAlign.right
        return TextHorizontalAlign.center
    }
    
    static rotation(disp: DispTextT): number {
        return disp.r
    }
    
    static text(disp: DispTextT): string {
        return disp.te
    }
    
    static setText(
        disp: DispTextT,
        val: string
    ): void {
        disp.te = val
        disp.bounds = null
    }
    
    static height(disp: DispTextT): number | null {
        return disp.th
    }
    
    static horizontalStretch(disp: DispTextT): number {
        return disp.hs
    }
    
    static centerPointX(disp: DispTextT): number {
        return disp.g[0]
    }
    
    static centerPointY(disp: DispTextT): number {
        return disp.g[1]
    }
    
    static center(disp: DispTextT): PointI {
        return {x: disp.g[0], y: disp.g[1]}
    }
    
    static setCenterPoint(
        disp: DispTextT,
        x: number,
        y: number
    ): void {
        disp.g = [x, y]
        disp.bounds = null
    }
    
    static create(coordSet: ModelCoordSet): DispTextT {
        let newDisp = {
            ...DispBase.create(coordSet, DispBase.TYPE_DT),
            // From Text
            "va": TextVerticalAlign.center, // TextVerticalAlign.center
            "ha": TextHorizontalAlign.center, // TextHorizontalAlign.center
            "r": 0, // number
            "th": null, // number | null
            "hs": 1, // number | null
        }
        
        DispText.setSelectable(newDisp, true)
        DispText.setText(newDisp, "New Text")
        
        let dispTextStyle = new DispTextStyle()
        dispTextStyle.id = coordSet.editDefaultTextStyleId
        
        let dispColor = new DispColor()
        dispColor.id = coordSet.editDefaultColorId
        
        DispText.setTextStyle(newDisp, dispTextStyle)
        DispText.setColor(newDisp, dispColor)
        
        DispText.setText(newDisp, "New Text")
        DispText.setCenterPoint(newDisp, 0, 0)
        
        return newDisp
    }
    
    static makeShapeContext(context: PeekCanvasShapePropsContext): void {
        DispBase.makeShapeContext(context)
        
        context.addProp(new ShapeProp(
            ShapePropType.MultilineString,
            DispText.text,
            DispText.setText,
            "Text"
        ))
        
        context.addProp(new ShapeProp(
            ShapePropType.TextStyle,
            DispText.textStyle,
            DispText.setTextStyle,
            "Text Style"
        ))
        
        context.addProp(new ShapeProp(
            ShapePropType.Color,
            DispText.color,
            DispText.setColor,
            "Color"
        ))
    }
    
    // ---------------
    // Represent the disp as a user friendly string
    
    static makeShapeStr(disp: DispTextT): string {
        let center = DispText.center(disp)
        return DispBase.makeShapeStr(disp)
            + `\nText : ${DispText.text(disp)}`
            + `\nAt : ${parseInt(<any>center.x)}x${parseInt(<any>center.y)}`
    }
    
}
