//
//  Style.swift
//  oosxl
//

import cxx_oosxl

public enum HAlignment: Int32 {
    case general = 0
    case left = 1
    case center = 2
    case right = 3
    case fill = 4
    case justify = 5
    case centerContinuous = 6
    case distributed = 7
}

public enum VAlignment: Int32 {
    case bottom = 0
    case center = 1
    case top = 2
    case justify = 3
    case distributed = 4
}

public enum BorderStyle: Int32 {
    case none = 0
    case thin = 1
    case medium = 2
    case thick = 3
    case double = 4
    case dashed = 5
    case mediumDashed = 6
    case dashDot = 7
    case mediumDashDot = 8
    case dashDotDot = 9
    case mediumDashDotDot = 10
    case slantDashDot = 11
    case dotted = 12
    case hair = 13
}

public enum BorderIndex: Int32 {
    case left = 0
    case right = 1
    case top = 2
    case bottom = 3
    case horizontal = 4
    case vertical = 5
    case diagonalDown = 6
    case diagonalUp = 7
    case edge = 8
    case inside = 9
}

public enum PatternType: Int32 {
    case none = 0
    case solid = 1
    case darkGray = 2
    case mediumGray = 3
    case lightGray = 4
    case gray125 = 5
    case gray0625 = 6
    case darkHorizontal = 7
    case darkVertical = 8
    case darkUp = 9
    case darkDown = 10
    case darkTrellis = 11
    case darkGrid = 12
    case lightHorizontal = 13
    case lightVertical = 14
    case lightUp = 15
    case lightDown = 16
    case lightTrellis = 17
    case lightGrid = 18
}

public enum RowHeightUnit: Int32 {
    case points = 0
    case inches = 1
    case millimeters = 2
}

public enum ColWidthUnit: Int32 {
    case chars = 0
    case inches = 1
    case millimeters = 2
}

public enum Underline: Int32 {
    case none = 0
    case single = 1
    case singleAccounting = 2
    case double = 3
    case doubleAccounting = 4
}

public class Style {
    let handle: StyleHandle
    let workbook: Workbook?

    public lazy var font: Font = {
        return Font(style: self)
    }()

    init(withHandle handle: StyleHandle, workbook: Workbook? = nil) {
        self.handle = handle
        self.workbook = workbook
        self.font = Font(style: self)
    }

    deinit {
    }
}

// MARK: number format
extension Style {
    public var numberFormat: String {
        get {
            if let cString = style_numfmt_code(handle) {
                return String(cString: cString)
            }
            return ""
        }
        set {
            style_set_numfmt(handle, newValue)
        }
    }

    public var numberFormatId: Int {
        get {
            return Int(style_numfmt_id(handle))
        }
        set {
            style_set_numfmt_id(handle, Int32(newValue))
        }
    }
}

extension Style {
    public struct Font {
        private unowned let style: Style

        init(style: Style) {
            self.style = style
        }

        public func set(name: String, size: Int) {
            style_set_font(style.handle, name, Int32(size))
        }

        public var name: String {
            get {
                guard let cString = style_font_name(style.handle) else { return "" }
                return String(cString: cString)
            }
            set {
                let currentSize = style_font_size(style.handle)
                style_set_font(style.handle, newValue, Int32(currentSize))
            }
        }

        public var size: Int {
            get {
                return Int(style_font_size(style.handle))
            }
            set {
                style_set_font_size(style.handle, Int32(newValue))
            }
        }

        public var bold: Bool {
            get {
                return style_bold(style.handle) != 0
            }
            set {
                style_set_bold(style.handle, newValue ? 1 : 0)
            }
        }

        public var italic: Bool {
            get {
                return style_italic(style.handle) != 0
            }
            set {
                style_set_italic(style.handle, newValue ? 1 : 0)
            }
        }

        public var strikeout: Bool {
            get {
                return style_strikeout(style.handle) != 0
            }
            set {
                style_set_strikeout(style.handle, newValue ? 1 : 0)
            }
        }

        public var color: COLORREF {
            get {
                return style_font_color(style.handle)
            }
            set {
                style_set_font_color(style.handle, newValue)
            }
        }

        public var underline: Underline {
            get {
                return Underline(rawValue: Int32(style_underlined(style.handle))) ?? .none
            }
            set {
                style_set_underline(style.handle, Int32(newValue.rawValue))
            }
        }
    }
}

// MARK: border
extension Style {
    public func setBorder(_ index: BorderIndex, style: BorderStyle, color: COLORREF? = nil) {
        style_set_border(handle, Int32(index.rawValue), Int32(style.rawValue))
        if let color = color {
            style_set_border_color(handle, Int32(index.rawValue), color)
        }
    }

    public func setBorderColor(_ index: BorderIndex, color: COLORREF) {
        style_set_border_color(handle, Int32(index.rawValue), color)
    }
}

// MARK: fill
extension Style {
    public var fillPattern: PatternType {
        get {
            return PatternType(rawValue: Int32(style_fill_pattern(handle))) ?? .none
        }
        set {
            style_set_fill_pattern(handle, Int32(newValue.rawValue))
        }
    }

    public var patternForegroundColor: COLORREF {
        get {
            return style_pattern_fg_color(handle)
        }
        set {
            style_set_pattern_fg_color(handle, newValue)
        }
    }

    public var patternBackgroundColor: COLORREF {
        get {
            return style_pattern_bg_color(handle)
        }
        set {
            style_set_pattern_bg_color(handle, newValue)
        }
    }
}

// MARK: alignment
extension Style {
    public var horizontalAlignment: HAlignment {
        get {
            return HAlignment(rawValue: Int32(style_align_h(handle))) ?? .general
        }
        set {
            style_set_align_h(handle, Int32(newValue.rawValue))
        }
    }

    public var verticalAlignment: VAlignment {
        get {
            return VAlignment(rawValue: Int32(style_align_v(handle))) ?? .bottom
        }
        set {
            style_set_align_v(handle, Int32(newValue.rawValue))
        }
    }

    public var wrapText: Bool {
        get {
            return style_wrap(handle) != 0
        }
        set {
            style_set_wrap(handle, newValue ? 1 : 0)
        }
    }

    public var rotation: Int {
        get {
            return Int(style_rotation(handle))
        }
        set {
            style_set_rotation(handle, Int32(newValue))
        }
    }

    public var indent: Int {
        get {
            return Int(style_indent(handle))
        }
        set {
            style_set_indent(handle, Int32(newValue))
        }
    }

    public var shrinkToFit: Bool {
        get {
            return style_shrink_to_fit(handle) != 0
        }
        set {
            style_set_shrink_to_fit(handle, newValue ? 1 : 0)
        }
    }
}

// MARK: protection
extension Style {
    public var locked: Bool {
        get {
            return style_cell_locked(handle) != 0
        }
        set {
            style_set_cell_locked(handle, newValue ? 1 : 0)
        }
    }

    public var hidden: Bool {
        get {
            return style_cell_hidden(handle) != 0
        }
        set {
            style_set_cell_hidden(handle, newValue ? 1 : 0)
        }
    }
}

// MARK: unapply
extension Style {
    public func unapplyNumberFormat() {
        style_unapply_numfmt(handle)
    }

    public func unapplyFont() {
        style_unapply_font(handle)
    }

    public func unapplyBorder() {
        style_unapply_border(handle)
    }

    public func unapplyFill() {
        style_unapply_fill(handle)
    }

    public func unapplyAlignment() {
        style_unapply_alignment(handle)
    }

    public func unapplyProtection() {
        style_unapply_protection(handle)
    }
}
