//
//  UIBezierPath+Helpers.swift
//  Tusker
//
//  Created by Shadowfacts on 6/25/20.
//  Copyright © 2020 Shadowfacts. All rights reserved.
//

import UIKit

// TODO: write unit tests for this
extension UIBezierPath {
    
    /// Create a new UIBezierPath that wraps around the given array of rectangles.
    /// This is not a convex hull aglorithm. What this does is it takes a set of rectangles
    /// and draws a line around the outer borders of the combined shape.
    convenience init(wrappingAround rects: [CGRect]) {
        precondition(rects.count > 0)
        
        if rects.count == 1 {
            self.init(rect: rects.first!)
            return
        }
        
        let rects = rects.sorted { $0.minY < $1.minY }
        
        self.init()
        
        // start at the top left corner
        self.move(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
        
        // walk down the left side
        var prevLeft = rects.first!.minX
        for rect in rects where !rect.minX.isEqual(to: prevLeft) {
            self.addLine(to: CGPoint(x: prevLeft, y: rect.minY))
            self.addLine(to: CGPoint(x: rect.minX, y: rect.minY))
            prevLeft = rect.minX
        }
        
        // ensure at the bottom left if not already
        let bottomLeft = CGPoint(x: rects.last!.minX, y: rects.last!.maxY)
        if !self.currentPoint.equalTo(bottomLeft) {
            self.addLine(to: bottomLeft)
        }
        
        // across the bottom of the last rect
        self.addLine(to: CGPoint(x: rects.last!.maxX, y: rects.last!.maxY))
        
        // walk up the right side
        var prevRight = rects.last!.maxX
        for rect in rects.reversed() where !rect.maxX.isEqual(to: prevRight) {
            self.addLine(to: CGPoint(x: prevRight, y: rect.maxY))
            self.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
            prevRight = rect.maxX
        }
        
        // ensure at the top right if not already
        let topRight = CGPoint(x: rects.first!.maxX, y: rects.first!.minY)
        if !self.currentPoint.equalTo(topRight) {
            self.addLine(to: topRight)
        }
        
        // across the top of the first rect
        self.addLine(to: CGPoint(x: rects.first!.minX, y: rects.first!.minY))
    }
    
}
