         mainPaneCount = max(1, mainPaneCount - 1)
     }
 }
-
-extension ThreeColumnLayout: FrameAssigner {}


import Silica

private enum Column {
    case left
    case middle
    case right
}

private enum Pane {
    case main
    case secondary
    case tertiary
}

private struct PaneArrangement {
    let mainPane: Column  // which Column is the main Pane

    let mainPaneCount: UInt  // how many windows in the main Pane
    let secondaryPaneCount: UInt  // how many windows in the secondary Pane
    let tertiaryPaneCount: UInt  // how many windows in the tertiary Pane

    let screenHeight: CGFloat  // total height of the screen
    let mainWindowHeight: CGFloat  // height of each window in the main Pane
    let secondaryWindowHeight: CGFloat  // height of each window in the secondary Pane
    let tertiaryWindowHeight: CGFloat  // height of each window in the tertiary Pane

    let screenWidth: CGFloat  // total width of the screen
    let mainWindowWidth: CGFloat  // width of each window in the main Pane
    let nonMainWindowWidth: CGFloat  // width of each window in the secondary or tertiary Pane

    init(mainPane: Column,  // which Column is the main Pane
         numWindows: UInt,  // how many windows total
         numMainPane: UInt,  // how many windows in the main Pane
         screenHeight: CGFloat,  // total height of the screen
         screenWidth: CGFloat,  // total width of the screen
         mainPaneRatio: CGFloat
    ) {
        self.mainPane = mainPane
        self.mainPaneCount = min(numWindows, numMainPane)
        let nonMainCount: UInt = numWindows - self.mainPaneCount
        self.secondaryPaneCount = nonMainCount >> 1
        self.tertiaryPaneCount = nonMainCount - self.secondaryPaneCount
        self.screenHeight = screenHeight
        self.screenWidth = screenWidth
        self.mainWindowHeight = round(screenHeight / CGFloat(self.mainPaneCount))
        self.secondaryWindowHeight = self.secondaryPaneCount > 0 ? round(screenHeight / CGFloat(self.secondaryPaneCount)) : 0.0
        self.tertiaryWindowHeight = self.tertiaryPaneCount > 0 ? round(screenHeight / CGFloat(self.tertiaryPaneCount)) : 0.0
        if self.tertiaryPaneCount > 0 {
            self.mainWindowWidth = round(self.screenWidth * mainPaneRatio)
            self.nonMainWindowWidth = round((self.screenWidth - self.mainWindowWidth) / 2)
        } else if self.secondaryPaneCount > 0 {
            // has a secondary pane, but no tertiary pane
            self.mainWindowWidth = round(self.screenWidth * mainPaneRatio)
            self.nonMainWindowWidth = self.screenWidth - self.mainWindowWidth
        } else {
            // has only a main pane
            self.mainWindowWidth = self.screenWidth
            self.nonMainWindowWidth = 0.0
        }
    }

    // Given a window index, which Pane does it belong to, and which index within that Pane
    func coordinates(at windowIndex: UInt) -> (Pane, UInt) {
        // main windows are indexes [0, mainPaneCount)
        // secondary windows are indexes [mainPaneCount, mainPaneCount + secondaryPaneCount)
        // tertiary windows are indexes [mainPaneCount + secondaryPaneCount, ...)
        if windowIndex < mainPaneCount {
            return (Pane.main, windowIndex)
        } else if windowIndex >= (mainPaneCount + secondaryPaneCount) {
            return (Pane.tertiary, windowIndex - mainPaneCount - secondaryPaneCount)
        } else {
            return (Pane.secondary, windowIndex - mainPaneCount)
        }
    }

    // Get the (height, width) dimensions for a window in the given Pane
    func windowDimensions(for pane: Pane) -> (CGFloat, CGFloat) {
        switch pane {
        case .main: return (mainWindowHeight, mainWindowWidth)
        case .secondary: return (secondaryWindowHeight, nonMainWindowWidth)
        case .tertiary: return (tertiaryWindowHeight, nonMainWindowWidth)
        }
    }

    // Get the Column assignment for the given Pane
    func column(for pane: Pane) -> Column {
        switch mainPane {
        case .left:
            switch pane {
            case .main: return Column.left
            case .secondary: return Column.middle
            case .tertiary: return Column.right
            }
        case .middle:
            switch pane {
            case .main: return Column.middle
            case .secondary: return Column.left
            case .tertiary: return Column.right
            }
        case .right:
            switch pane {
            case .main: return Column.right
            case .secondary: return Column.left
            case .tertiary: return Column.middle
            }
        }
    }

    // Get the column widths in the order (left, middle, right)
    func widthsLeftToRight() -> (CGFloat, CGFloat, CGFloat) {
        switch mainPane {
        case .left: return (mainWindowWidth, nonMainWindowWidth, nonMainWindowWidth)
        case .middle: return (nonMainWindowWidth, mainWindowWidth, nonMainWindowWidth)
        case .right: return (nonMainWindowWidth, nonMainWindowWidth, mainWindowWidth)
        }
    }
}

final class ThreeColumnReflowOperation: ReflowOperation {
    private let layout: ThreeColumnLayout
    private let mainIs: Column

    fileprivate init(screen: NSScreen, windows: [SIWindow], layout: ThreeColumnLayout, frameAssigner: FrameAssigner, mainIs: Column) {
        self.layout = layout
        self.mainIs = mainIs
        super.init(screen: screen, windows: windows, frameAssigner: frameAssigner)
    }

    func frameAssignments() -> [FrameAssignment] {

        }

        let screenFrame = screen.adjustedFrame()
        let paneArrangement = TriplePaneArrangement(mainPane: layout.mainColumn,
                                              numWindows: UInt(windows.count),
                                              numMainPane: UInt(layout.mainPaneCount),
                                              screenSize: screenFrame.size,
                                              mainPaneRatio: layout.mainPaneRatio)

        let focusedWindow = SIWindow.focused()
