 import Darwin
 import UIKit
 
+public protocol DSRadialMenuDelegate: class {
+    func menuItemTapped(menuItem: DSRadialMenu.MenuItem)
+}
+
 public class DSRadialMenu: UIView {
     
-    typealias MenuItem = (button: UIButton, positon: MenuItemPositon)
+    public typealias MenuItem = (button: UIButton, position: MenuItemPosition)
 
-    @IBInspectable public var menuItemSize: CGSize = CGSizeZero
-    @IBInspectable var distanceFromCenter: Double = 100
+    @IBOutlet public weak var centerButton: UIButton!
+    
+    @IBInspectable public var menuItemSize = CGSize(width: 50, height: 50)
+    @IBInspectable public var distanceFromCenter: Double = 100
     
     var distanceBetweenMenuItems: Double = 30
-
+    private(set) public var menuItems = [MenuItem]()
     private(set) public var state: MenuState = .Closed
-    private(set) var menuItems = [MenuItem]()
-    
-    public var tappedMenuItem: ((String, MenuItemPositon) -> Void)?
+    public weak var delegate: DSRadialMenuDelegate?
     
     public enum MenuState {
         case Open
         case Closed
     }
     
-    public enum MenuItemPositon: Int {
+    public enum MenuItemPosition: Int {
         case Center = -1
         case TwelveOClock = 0
         case OneOClock = 1

        case ElevenOClock = 11
    }
    
    func calculateMenuItemPoint(position: MenuItemPositon) -> CGPoint {
        let π = M_PI
        let angle: Double = (distanceBetweenMenuItems * Double(position.rawValue))
        let cosine = cos(angle / Double(180.0) * π)
        let sine = sin(angle / Double(180.0) * π)
        let deltaY: Double = -distanceFromCenter * cosine
        let deltaX: Double = distanceFromCenter * sine
        let point = CGPoint(x: deltaX, y: deltaY)
        return point
    }
    
    func addButtonConstraints(button: UIButton, size: CGSize) {
        addConstraint(NSLayoutConstraint(item: button, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: size.width))
        addConstraint(NSLayoutConstraint(item: button, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: size.height))
        addConstraint(NSLayoutConstraint(item: button, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 1))
        addConstraint(NSLayoutConstraint(item: button, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 1))
    }

    public func addMenuItem<T: UIButton>(title: String, position: MenuItemPositon) -> T {
        return addMenuItem(title, position: position, size: menuItemSize)        
    }
    
    public func addMenuItem<T: UIButton>(title: String, position: MenuItemPositon, size: CGSize) -> T {
        let button = T()
        button.setTranslatesAutoresizingMaskIntoConstraints(false)
        button.setTitle(title, forState: .Normal)
        button.tag = position.rawValue
        button.addTarget(self, action: "tappedMenuItem:", forControlEvents: .TouchUpInside)
        addSubview(button)
        sendSubviewToBack(button)
        addButtonConstraints(button, size: size)

        state = .Closed
    }
    
    public func nextMenuItemPosition() -> MenuItemPosition? {
        let takenPositions = menuItems.map( { $0.position.rawValue } )
        let freePositions = [Int](MenuItemPosition.TwelveOClock.rawValue...MenuItemPosition.ElevenOClock.rawValue).filter() {
            return find(takenPositions, $0) == nil
        }
        if freePositions.isEmpty {
            return nil
        } else {
            return MenuItemPosition(rawValue: freePositions.first!)
        }
    }
    
    // MARK: Internal
    
    func animateMenuItemOut(menuItem: MenuItem) {
        menuItem.button.hidden = false
        let point = calculateMenuItemPoint(menuItem.position)
        UIView.animateWithDuration(0.4, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.6, options: .CurveEaseInOut, animations: { () -> Void in
            menuItem.button.transform = CGAffineTransformMakeTranslation(point.x, point.y)
            }, completion: nil)
