// ---------------------------------------------------------------------------
// PeekCanvasBounds
// ---------------------------------------------------------------------------
export class PeekCanvasBounds {
    x: number
    y: number
    w: number
    h: number
    
    constructor(
        x: number | PeekCanvasBounds = 0.0,
        y: number = 0.0,
        w: number = 0.0,
        h: number = 0.0
    ) {
        
        // Copy constructor
        if (x instanceof PeekCanvasBounds) {
            this.x = parseFloat(x.x.toString())
            this.y = parseFloat(x.y.toString())
            this.w = parseFloat(x.w.toString())
            this.h = parseFloat(x.h.toString())
            return
        }
        
        this.x = 0.0
        this.y = 0.0
        this.w = 0.0
        this.h = 0.0
        
        if (x)
            this.x = parseFloat(x.toString())
        
        if (y)
            this.y = parseFloat(y.toString())
        
        if (w)
            this.w = parseFloat(w.toString())
        
        if (h)
            this.h = parseFloat(h.toString())
        
        if (this.w < 0) {
            this.w *= -1
            this.x = this.x - this.w
        }
        
        if (this.h < 0) {
            this.h *= -1
            this.y = this.y - this.h
        }
    }
    
    // Class method
    static fromPoints(points: { x: number, y: number }[]) {
        let geom = []
        for (let point of points) {
            geom.push(point.x)
            geom.push(point.y)
        }
        return PeekCanvasBounds.fromGeom(geom)
    }
    
    // Class method
    static fromGeom(geom) {
        const self = new PeekCanvasBounds()
        
        self.x = geom[0] // Low x
        self.y = geom[1] // Upper x
        self.w = 0
        self.h = 0
        
        self.increaseFromGeom(geom)
        
        return self
    }
    
    increaseFromGeom(geom) {
        let ux = this.x + this.w
        let uy = this.y + this.h
        
        for (let i = 0; i < geom.length; i += 2) {
            let pointX = geom[i]
            let pointY = geom[i + 1]
            
            // Work out our bounds
            if (pointX < this.x)
                this.x = pointX
            
            if (ux < pointX)
                ux = pointX
            
            if (pointY < this.y)
                this.y = pointY
            
            if (uy < pointY)
                uy = pointY
        }
        
        this.w = ux - this.x
        this.h = uy - this.y
    };
    
    increaseFromBounds(bounds) {
        
        let rx = this.x + this.w // Right X
        let by = this.y + this.h // Bottom Y
        
        const orx = bounds.x + bounds.w // Right X
        const oby = bounds.y + bounds.h // Bottom Y
        
        // Work out our bounds
        if (bounds.x < this.x)
            this.x = bounds.x
        
        if (rx < orx)
            rx = orx
        
        if (bounds.y < this.y)
            this.y = bounds.y
        
        if (by < oby)
            by = oby
        
        this.w = rx - this.x
        this.h = by - this.y
    };
    
    contains(
        x,
        y,
        margin
    ) {
        let b = this
        
        // For Bounding Box
        let left = b.x - margin / 2
        let right = b.x + b.w + margin / 2
        let top = b.y - margin / 2
        let bottom = b.y + b.h + margin / 2
        
        return (left <= x && x <= right) //
            && (top <= y && y <= bottom)
    };
    
    withIn(
        x,
        y,
        w,
        h
    ) {
        if (x instanceof PeekCanvasBounds) {
            y = x.y
            w = x.w
            h = x.h
            x = x.x
        }
        
        let b = this
        return (x <= b.x) && (b.x + b.w <= x + w) //
            && (y <= b.y) && (b.y + b.h <= y + h)
    };
    
    isEqual(other) {
        
        if (!(other instanceof PeekCanvasBounds))
            return false
        
        return (this.x === other.x) //
            && (this.y === other.y) //
            && (this.w === other.w) //
            && (this.h === other.h) //
        
    };
    
    area() {
        return this.w * this.h
    };
    
    center(): { x: number, y: number } {
        return {
            x: this.x + this.w / 2,
            y: this.y + this.h / 2
        }
    };
    
    distanceFromPoint(point: { x: number, y: number }): number {
        let center = this.center()
        return Math.sqrt(
            Math.pow(center.x - point.x, 2)
            + Math.pow(center.y - point.y, 2)
        )
    }
    
    toString() {
        return `${this.x}x,${this.y}y,${this.w}w,${this.h}h`
    }
}

            