import UIKit
import PlaygroundSupport
import SnapKit

var horzPadding = 20
var vertPadding = 20

class ActionTarget {
    
    let closure: () -> ()
    
    init(closure: @escaping () -> ()) {
        self.closure = closure
    }
    
    @objc func action(val: Int) {
        closure()
    }
}

// new up elements
let view = UIView()
view.backgroundColor = UIColor.white

let vc = UIViewController()
vc.view = view

let firstNameLabel = UILabel()
firstNameLabel.text = "First Name"
view.addSubview(firstNameLabel)

let firstNameField = UITextField()
firstNameField.borderStyle = .roundedRect
view.addSubview(firstNameField)

let lastNameLabel = UILabel()
lastNameLabel.text = "Last Name"
view.addSubview(lastNameLabel)

let lastNameField = UITextField()
lastNameField.borderStyle = .roundedRect
view.addSubview(lastNameField)

let horzSlider = UISlider()
horzSlider.minimumValue = 0
horzSlider.maximumValue = 50
horzSlider.value = Float(horzPadding)
view.addSubview(horzSlider)

let vertSlider = UISlider()
vertSlider.minimumValue = 0
vertSlider.maximumValue = 50
vertSlider.value = Float(vertPadding)
view.addSubview(vertSlider)

let animButton = UIButton()
animButton.backgroundColor = UIColor.green
animButton.setTitle("Animate", for: UIControlState.normal)
view.addSubview(animButton)

// setup constraints
var leftConstraint: ConstraintMakerEditable? = nil
var rightConstraint: ConstraintMakerEditable? = nil

var topConstraints: [Constraint] = []

horzSlider.snp.makeConstraints { (make) in
    make.top.equalTo(vc.topLayoutGuide.snp.bottom).offset(20).constraint
    make.left.equalTo(view).offset(horzPadding)
    make.right.equalTo(view).offset(-horzPadding)
}

vertSlider.snp.makeConstraints { (make) in
    make.top.equalTo(horzSlider.snp.bottom).offset(20).constraint
    make.left.equalTo(view).offset(horzPadding)
    make.right.equalTo(view).offset(-horzPadding)
}

firstNameLabel.snp.makeConstraints { (make) -> Void in
    topConstraints.append(make.top.equalTo(vertSlider.snp.bottom).offset(vertPadding).constraint)
    leftConstraint = make.left.equalTo(view).offset(horzPadding)
    rightConstraint = make.right.equalTo(view).offset(-horzPadding)
}

firstNameField.snp.makeConstraints { (make) -> Void in
    make.top.equalTo(firstNameLabel.snp.bottom)
    make.left.equalTo(firstNameLabel)
    make.right.equalTo(firstNameLabel)
}

lastNameLabel.snp.makeConstraints { (make) in
    topConstraints.append(make.top.equalTo(firstNameField.snp.bottom).offset(vertPadding).constraint)
    make.left.equalTo(firstNameLabel)
    make.right.equalTo(firstNameLabel)
}

lastNameField.snp.makeConstraints { (make) in
    make.top.equalTo(lastNameLabel.snp.bottom)
    make.left.equalTo(firstNameLabel)
    make.right.equalTo(firstNameLabel)
}

animButton.snp.makeConstraints { (make) in
    topConstraints.append(make.top.equalTo(lastNameField.snp.bottom).offset(vertPadding).constraint)
    make.left.equalTo(firstNameLabel)
    make.right.equalTo(firstNameLabel)
    make.height.equalTo(40)
}

// wire up

let slideXTarget = ActionTarget() {
    horzPadding = Int(horzSlider.value)

    print ("horz: \(horzPadding)")
    
    // Route 1:
    leftConstraint?.constraint.update(offset: horzPadding)
    rightConstraint?.constraint.update(offset: -horzPadding)
    
    // Route 2:
//    firstNameLabel.snp.updateConstraints { (make) -> Void in
//        make.left.equalTo(view).offset(horzPadding)
//        make.right.equalTo(view).offset(-horzPadding)
//    }
}

let slideYTarget = ActionTarget() {
    vertPadding = Int(vertSlider.value)
    
    for var c in topConstraints
    {
        c.update(offset: vertPadding)
    }
}


let animatedTarget = ActionTarget() {
    
    var newHorzPadding: Int = 0
    
    if (horzPadding == 50) {
        newHorzPadding = 0
    } else {
        newHorzPadding = 50
    }

    leftConstraint?.constraint.update(offset: newHorzPadding)
    rightConstraint?.constraint.update(offset: -newHorzPadding)
    view.setNeedsLayout()
    
    UIView.animate(withDuration: 0.2, animations: { () -> Void in
        view.layoutIfNeeded()
    }, completion: {
        (value: Bool) in
        horzPadding = newHorzPadding
        horzSlider.value = Float(horzPadding)
    })
}

horzSlider.addTarget(slideXTarget, action: #selector(ActionTarget.action), for: .valueChanged)
vertSlider.addTarget(slideYTarget, action: #selector(ActionTarget.action), for: .valueChanged)
animButton.addTarget(animatedTarget, action: #selector(ActionTarget.action), for: .touchUpInside)

PlaygroundPage.current.liveView = vc
vc