import { addTupleType, Tuple } from "@synerty/vortexjs"
import { diagramTuplePrefix } from "../PluginNames"
import { ModelCoordSetGridSize } from "./ModelCoordSetGridSize"
import { PeekCanvasBounds } from "../PeekCanvasBounds"

/* Make Disp Group Grid Key
 
 Make the special disp group grid key name.
 This is used to store all of the DispGroups that are not specifically stored in a
 grid, with the DispGroupPtr that uses it.
 
 */
export function makeDispGroupGridKey(coordSetId: number): string {
    return `${coordSetId}|dispgroup`
}

@addTupleType
export class ModelCoordSet extends Tuple {
    public static readonly tupleName = diagramTuplePrefix + "ModelCoordSet"
    
    id: number
    key: string
    name: string
    initialPanX: number
    initialPanY: number
    initialZoom: number
    
    // The pre-configured zoom level for this coord set to use when positioning.
    positionOnZoom: number
    
    enabled: boolean
    
    comment: string
    
    modelSetId: number
    
    minZoom: number
    maxZoom: number
    
    gridSizes: ModelCoordSetGridSize[]
    
    // Misc data holder
    data: { [key: string]: any } | null
    
    // Show this Coord Set as a group of DispGroups to choose from in the Editor
    dispGroupTemplatesEnabled: boolean
    
    // Show this Coord Set as a group of Line Templates to choose from in the Editor
    edgeTemplatesEnabled: boolean
    
    // Show "Select Branches" button
    branchesEnabled: boolean
    
    // Edit fields
    editEnabled: boolean
    
    // Default Layer for new shapes
    editDefaultLayerId: number
    
    // Default Level for new shapes
    editDefaultLevelId: number
    
    // Default Color for new shapes
    editDefaultColorId: number
    
    // Default Line for new shapes
    editDefaultLineStyleId: number
    
    // Default Text for new shapes
    editDefaultTextStyleId: number
    
    // Default Vertex/Node/Equipment Coord Set
    editDefaultVertexCoordSetId: number
    editDefaultVertexGroupName: string
    
    // Default Edge/Conductor Coord Set
    editDefaultEdgeCoordSetId: number
    editDefaultEdgeGroupName: string
    
    // is this the landing coord set?
    isLanding: boolean
    
    constructor() {
        super(ModelCoordSet.tupleName)
    }
    
    /** Grid size for Zoom
     *
     * This method calculates which Z grid to use based on a zoom level
     */
    gridSizeForZoom(zoom: number): ModelCoordSetGridSize {
        if (zoom == null)
            throw new Error("Zoom can't be null")
        
        // Figure out the Z grid
        for (let gridSize of this.gridSizes) {
            if (gridSize.min <= zoom && zoom < gridSize.max) {
                return gridSize
            }
        }
        throw new Error(`Unable to determine grid size for zoom ${zoom}`)
    }
    
    /** Grid Keys For Area
     *
     * This method returns the grids required for a certain area of a certain zoom level.
     *
     */
    gridKeysForArea(
        area: PeekCanvasBounds,
        zoom: number
    ): string[] {
        
        function trunc(num: any) {
            return parseInt(num)
        }
        
        let gridSize = this.gridSizeForZoom(zoom)
        
        // Round the X min/max
        let minGridX = trunc(area.x / gridSize.xGrid)
        let maxGridX = trunc((area.x + area.w) / gridSize.xGrid) + 1
        
        // Round the Y min/max
        let minGridY = trunc(area.y / gridSize.yGrid)
        let maxGridY = trunc((area.y + area.h) / gridSize.yGrid) + 1
        
        // Iterate through and create the grids.
        let gridKeys = []
        for (let x = minGridX; x < maxGridX; x++) {
            for (let y = minGridY; y < maxGridY; y++) {
                gridKeys.push(this.id.toString() + "|" + gridSize.key + "." + x + "x" + y)
            }
        }
        
        return gridKeys
    }
}