//
//  MINTLDividerViewController.swift
//  ToDoList
//
//  Created by narita on 2017/09/12.
//  Copyright © 2017年 narita. All rights reserved.
//

import Cocoa

/**
 主な編集対象のドキュメントを表示するViewを分割表示するための機能をもたせたSpliterViewの支援ViewController
 既存のSpliterの用途はWindowをInspectorやToolPalette用に分割するためのものであった。
 
 */

class MINTLDividerViewController: NSSplitViewController
{
    // MARK: - class methods
    
    // MARK: - init methods
    
    // MARK: - dealloc
    
    // MARK: - NSCopying, hash, isEqual:
    
    // MARK: - NSCoding methods
    
    // MARK: - restorableState methods
    
    override func encodeRestorableState(with coder: NSCoder)
    {
        super.encodeRestorableState(with: coder)
        
        // 分割位置の保存
        coder.encode(self.positionsArray, forKey: "splitSizes")
    }
    
    override func restoreState(with coder: NSCoder)
    {
        super.restoreState(with: coder)
        
        let theSplitSizes:NSArray? = coder.decodeObject(forKey: "splitSizes") as! NSArray?
        
        // 個数分分割して
        let theSplitCount = theSplitSizes!.count
        
        while theSplitCount != self.countOfDivider + 1
        {
            let theItem: NSSplitViewItem = self.makeNewSplitViewItem()!
            self.addSplitViewItem(theItem)
        }
        
        // 幅を整える
        self.positionsArray = theSplitSizes
        self.invalidateRestorableState()
    }

    // MARK: - life cycle methods
    
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        let theItem: NSSplitViewItem = self.makeNewSplitViewItem()!
        self.addSplitViewItem(theItem)
    }
    
    
    // MARK: - action methods
    
    func makeNewSplitViewItem() -> NSSplitViewItem?
    {
        let theStoryboard: NSStoryboard? =
            NSStoryboard.init(name: self.splitedViewItemStoryboardName,
                              bundle: nil)
        
        let theViewController: NSViewController? =
            theStoryboard?.instantiateInitialController() as! NSViewController?
        
        let theItem: NSSplitViewItem?  =
            NSSplitViewItem.init( viewController :theViewController!)
        
        return theItem
    }

    @objc func insertNewPane(after viewController : NSViewController?)
    {
        let theCurrentItem: NSSplitViewItem? = self.splitViewItem(for: viewController!)
        let theIndex: NSInteger = self.splitViewItems.index(of: theCurrentItem!)!
        
        let theNewItem: NSSplitViewItem? = self.makeNewSplitViewItem()
        
        // 区切り線の位置を保存して
        let theArray: NSMutableArray? = self.positionsArray!.mutableCopy() as? NSMutableArray
        
        // スクロール位置の調整の準備
        let theCurrentScrollerView: NSScrollView? = theCurrentItem?.viewController.view as! NSScrollView?
        let theCurrentRect: NSRect = theCurrentScrollerView!.contentView.bounds
        
        // 区切り線を挿入
        self.insertSplitViewItem(theNewItem!, at: theIndex+1)

        // 挿入後に区切り線の位置を調整して復帰
        let thePosition_0: CGFloat = CGFloat(theIndex != 0 ? (theArray![theIndex-1] as! NSNumber).doubleValue : 0.0)
        let thePosition_1: CGFloat = CGFloat((theArray![theIndex] as! NSNumber ).doubleValue)
        let thePosition_2: CGFloat = CGFloat(roundf( Float((thePosition_1 - thePosition_0) / 2.0))) + thePosition_0
        theArray?.insert(thePosition_2, at: theIndex)

        self.positionsArray = theArray
        
        // 新しく作ったviewのスクロール位置を調整
        let theNewScrollerView: NSScrollView?  = theNewItem?.viewController.view as! NSScrollView?

        var theNewRect: NSRect = theNewScrollerView!.contentView.bounds
        theNewRect.origin.y = theCurrentRect.origin.y + theCurrentRect.size.height / 2
        
        // 理由は不明だが、自動でスクロール位置が変更されてしまうために、遅延実行している
        OperationQueue.main.addOperation
        {
            theNewScrollerView!.contentView.bounds = theNewRect
        }
        
        self.view.window?.makeFirstResponder(theNewItem?.viewController.view)
        
        self.invalidateRestorableState()
    }

    
    @objc func removePane(_ viewController : NSViewController?)
    {
        if !self.splitViewItems.isEmpty
        {
            let theItem: NSSplitViewItem? = self.splitViewItem(for: viewController!)
            let theIndex: NSInteger = self.splitViewItems.index(of: theItem!)!

            // 区切り線の位置を保存して
            let theArray: NSMutableArray? = self.positionsArray!.mutableCopy() as? NSMutableArray

            // theItem.viewControllerがアクティブなレスポンダーチェインに属しているならば、
            // 削除により、firstResponderのポイント先がなくなるので変更する
            var theResetFirstResponder: Bool = false

            var theResponder: NSResponder? = self.view.window?.firstResponder
            
            while  theResponder != nil
            {
                if theResponder == theItem?.viewController
                {
                    theResetFirstResponder = true
                    
                    break
                }
                else
                {
                    theResponder = theResponder?.nextResponder
                }
            }

            // TODO:スクロール位置の調整とアニメーション
            self.removeSplitViewItem(theItem!)
            
            // 区切り線の位置を調整して復帰
            theArray?.removeObject(at: max(0, theIndex-1))
            self.positionsArray = theArray
            
            //削除するPaneからフォーカスを変更
            if theResetFirstResponder
            {
                self.makeFirstResponderAtIndex(max(theIndex-1, 0))
            }
            
            self.invalidateRestorableState()
        }
    }

    func makeFirstResponderAtIndex(_ inIndex: NSInteger)
    {
        let theIndex = min(inIndex, self.splitViewItems.count - 1)
        
        let theItem: NSSplitViewItem? = self.splitViewItems[theIndex]
        
        self.view.window?.makeFirstResponder(theItem?.viewController.view)
    }
    
    // MARK: - event handling methods
    
    // MARK: - drawing methods
    
    // MARK: - delegate/datasource methods
        // 分割線を移動する時にscrollViewの中身をそれに合わせてスクロールさせる
    static var sOldPosition: CGFloat = 0
    
    override func splitViewWillResizeSubviews(_ notification: Notification)
    {
        let theUserInfo: NSObject? = notification.userInfo as NSObject?
        let theBool:     NSNumber? = theUserInfo?.value(forKey: "NSSplitViewUserResizeKey") as! NSNumber?
        
        if theBool?.boolValue == true
        {
            let theIndexObject: NSNumber? = theUserInfo?.value(forKey: "NSSplitViewDividerIndex") as! NSNumber?
            
            let theIndex: NSInteger = theIndexObject!.intValue

            MINTLDividerViewController.sOldPosition = self.positionOfDividerAtIndex(theIndex)
        }
    }

    override func splitViewDidResizeSubviews(_ notification: Notification)
    {
        let theUserInfo: NSObject? = notification.userInfo as NSObject?
        let theBool:     NSNumber? = theUserInfo?.value(forKey: "NSSplitViewUserResizeKey") as! NSNumber?
        
        if theBool?.boolValue == true
        {
            let theIndexObject: NSNumber? = theUserInfo?.value(forKey: "NSSplitViewDividerIndex") as! NSNumber?
            
            let theIndex: NSInteger = theIndexObject!.intValue
            
            let theCurrentPosition: CGFloat = self.positionOfDividerAtIndex(theIndex)
            
            let theItem: NSSplitViewItem? = self.splitViewItems[theIndex+1]
            let theScrollerView: NSScrollView = theItem!.viewController.view as! NSScrollView
            
            var theRect: NSRect = theScrollerView.contentView.bounds
            theRect.origin.y += theCurrentPosition - MINTLDividerViewController.sOldPosition
            
            theScrollerView.contentView.bounds = theRect //TODO:コメントアウト
        }
    }
    
    // MARK: - accessor methods (in pairs)
    
    // この名前のStoryBoardで定義されているviewControllerを読み込むサブクラスでオーバーライドすること
    // @IBInspectableで設定可能にしてはいけない。awakeFromNibの前にこのプロパティが使用されるのでサブクラス化すること。
    @objc var splitedViewItemStoryboardName: String
    {
        get
        {
            return ""
        }
    }
    
    @objc var positionsArray: NSArray?
    {
        get
        {
            let theArray: NSMutableArray? = NSMutableArray.init()
        
            for i in 0...self.countOfDivider
            {
                let thePosition:CGFloat = self.positionOfDividerAtIndex(i)
                
                theArray?.add(thePosition)
            }
            
            return theArray?.copy() as! NSArray?
        }
        
        set(value)
        {
            for i in 0...(value!.count - 1)
            {
                let thePosition: CGFloat = CGFloat((value![i] as! NSNumber).floatValue)
                
                self.splitView.setPosition(thePosition, ofDividerAt: i)
            }
        }
    }
    
    @objc var countOfDivider: NSInteger
    {
        let theCount: NSInteger = self.splitViewItems.count
        
        return (theCount == 0 ) ? 0 : theCount - 1
    }
    
    // MARK: - Utility methods
    
    func setPosition(_ position: CGFloat, ofDividerAtIndex dividerIndex: NSInteger)
    {
        self.splitView.setPosition(position, ofDividerAt: dividerIndex)
    }
    
    func positionOfDividerAtIndex(_ dividerIndex: NSInteger) -> CGFloat
    {
        var thePosition: CGFloat = 0
    
        for i in 0...dividerIndex
        {
            let theItem: NSSplitViewItem = self.splitViewItems[i]
            let theFrame: NSRect         = theItem.viewController.view.frame
            
            thePosition += theFrame.size.height
            
            // 2個目のitem以降にはdividerThicknessを含める
            if i != 0
            {
                thePosition += self.splitView.dividerThickness
            }
        }
        
        return thePosition
    }
}
