// 模拟依赖属性和相关类型
class DependencyProperty {
    static Register(name: string, type: any, ownerType: any, metadata: any) {
        return new DependencyProperty();
    }
}

class FrameworkPropertyMetadata {
    constructor(defaultValue: any) { }
}

class Brush { }
class SolidColorBrush extends Brush { }
class Pen {
    constructor(brush: Brush, thickness: number) { }
}
class Colors {
    static get Red() { return new SolidColorBrush(); }
}

class UIElement {
    IsVisible: boolean = true;
}

class FrameworkElement extends UIElement {
    RenderSize = { width: 0, height: 0 };
}

class DrawingContext {
    constructor(private canvasContext: CanvasRenderingContext2D) { }

    DrawLine(pen: Pen, startPoint: { x: number, y: number }, endPoint: { x: number, y: number }) {
        this.canvasContext.beginPath();
        this.canvasContext.moveTo(startPoint.x, startPoint.y);
        this.canvasContext.lineTo(endPoint.x, endPoint.y);
        this.canvasContext.stroke();
    }
}

class Rect {
    constructor(public size: { width: number, height: number }) { }//TODO 将height由0改为number

    get TopLeft() { return { x: 0, y: 0 }; }
    get TopRight() { return { x: this.size.width, y: 0 }; }
    get BottomLeft() { return { x: 0, y: this.size.height }; }
    get BottomRight() { return { x: this.size.width, y: this.size.height }; }
}

class Point {
    constructor(public x: number, public y: number) { }
}

class Application {
    static get Current() {
        return {
            TryFindResource(name: string) {
                return null;
            }
        };
    }
}

class Adorner {
    constructor(public AdornedElement: FrameworkElement) { }
    InvalidateVisual() { }
}

class FocusAdorner extends Adorner {
    static FocusAdornerPen: Pen;

    static BorderBrushProperty = DependencyProperty.Register("BorderBrush", Brush, FocusAdorner, new FrameworkPropertyMetadata(new SolidColorBrush()));
    static BorderThicknessProperty = DependencyProperty.Register("BorderThickness", Number, FocusAdorner, new FrameworkPropertyMetadata(2));

    get BorderBrush() { return null; }
    set BorderBrush(value: Brush) { }

    get BorderThickness() { return 2; }
    set BorderThickness(value: number) { }

    private _close: () => void;

    constructor(adornedElement: FrameworkElement, private canvasContext: CanvasRenderingContext2D) {
        super(adornedElement);
        const dpd = {
            AddValueChanged: (element: UIElement, handler: () => void) => { },
            RemoveValueChanged: (element: UIElement, handler: () => void) => { }
        };
        const handler = () => {
            this.InvalidateVisual();
        };
        dpd.AddValueChanged(adornedElement, handler);
        this._close = () => {
            dpd.RemoveValueChanged(adornedElement, handler);
        };
    }

    static {
        FocusAdorner.FocusAdornerPen = Application.Current.TryFindResource("FocusAdorner_Normal_Pen") as Pen;
        if (!FocusAdorner.FocusAdornerPen) {
            FocusAdorner.FocusAdornerPen = new Pen(new SolidColorBrush(), 1.0);
        }
    }

    Close() {
        this._close();
    }

    InvalidateVisual() {
        const drawingContext = new DrawingContext(this.canvasContext);
        this.OnRender(drawingContext);
    }

    protected OnRender(drawingContext: DrawingContext) {
        if (!this.AdornedElement || !this.AdornedElement.IsVisible) return;

        const adornedElementRect = new Rect(this.AdornedElement.RenderSize);

        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y - 3), new Point(adornedElementRect.TopLeft.x + 5, adornedElementRect.TopLeft.y - 3));
        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y - 3), new Point(adornedElementRect.TopLeft.x - 3, adornedElementRect.TopLeft.y + 5));

        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y - 3), new Point(adornedElementRect.TopRight.x - 5, adornedElementRect.TopRight.y - 3));
        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y - 3), new Point(adornedElementRect.TopRight.x + 3, adornedElementRect.TopRight.y + 5));

        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y + 3), new Point(adornedElementRect.BottomLeft.x + 5, adornedElementRect.BottomLeft.y + 3));
        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y + 3), new Point(adornedElementRect.BottomLeft.x - 3, adornedElementRect.BottomLeft.y - 5));

        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y + 3), new Point(adornedElementRect.BottomRight.x - 5, adornedElementRect.BottomRight.y + 3));
        drawingContext.DrawLine(FocusAdorner.FocusAdornerPen, new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y + 3), new Point(adornedElementRect.BottomRight.x + 3, adornedElementRect.BottomRight.y - 5));
    }
}
