//
//  NSResponder+MINTLResponderForKey.swift
//  DateBook
//
//  Created by narita on 2017/09/06.
//  Copyright © 2017年 narita. All rights reserved.
//

import Cocoa

extension NSResponder
{
    // responder chainを下るsetValueForKey
    func setValue(_ value: Any?, toRespondableObjectForKey key: String) -> Bool
    {
        let theObject = self.findRespondableObject(of: key)
        
        if theObject != nil
        {
            theObject!.setValue(value, forKey: key)
            
            return true
        }
        
        return false
    }

    // responder chainを下るvalueForKey
    func valueFromRespondableObject(forKey key: String) -> NSObject?
    {
        let theObject = self.findRespondableObject(of: key)

        if theObject != nil
        {
            return theObject!.value(forKey: key) as! NSObject?
        }
        
        return nil
    }

    // objectを起点にresponder chainを下り、selectorのメソッドをもつインスタンスを探し出す
    func findRespondableObject(_ object: NSObject, withAction selector: Selector) -> NSObject?
    {
        var theResult: NSObject? = object;

        while ( theResult != nil )
        {
            if theResult!.responds(to: selector)
            {
                return theResult
            }
            
            if let theResponder = theResult as! NSResponder?
            {
                var theNextResponder = theResponder.nextResponder
                
                // windowControllerのdocumentはresponderチェインから外れているのでチェックする必要がある
                if theNextResponder == nil && theResponder is NSWindowController
                {
                    theNextResponder = theResponder.value(forKey: "document") as! NSResponder?
                }
                
                theResult = theNextResponder
            }
            else
            {
                break
            }
        }

        // Application delegateはresponderチェインから外れているのでチェック
        if NSApp.delegate!.responds(to: selector)
        {
            return NSApp.delegate as! NSObject?
        }
        
        // NSDocumentControllerもresponderチェインから外れているのでチェック
        if NSDocumentController.shared.responds(to: selector)
        {
            return NSDocumentController.shared
        }

        // レスポンダーチェインから外れているように見えたので念のため追加
        if NSApp.responds(to: selector)
        {
            return NSApp
        }
        
        return nil
    }

    // objectを起点にresponder chainを下り、keyをプロパティーにもつインスタンスを探し出す
    func findRespondableObject(_ object: NSObject, withKey key: String) -> NSObject?
    {
        var theResult: NSObject? = object;
        
        while ( theResult != nil )
        {
            if theResult?.propertyExists(at: key) == .readWrite
            {
                return theResult
            }
            
            if ( theResult is NSWindow || theResult is NSApplication )
            {
                if theResult?.propertyExists(at:"delegate") == .readWrite
                {
                    let theDelegate:NSObject? = theResult?.value(forKey: "delagate") as! NSObject?
                    
                    if theDelegate!.propertyExists(at:key) == .readWrite
                    {
                        return theDelegate
                    }
                }
            }

            if let theWindowController = theResult as! NSWindowController?
            {
                if let theDocument = theWindowController.document as! NSDocument?
                {
                    if theDocument.propertyExists(at:key) == .readWrite
                    {
                        return theDocument
                    }
                }
            }
            
            if let theResponder = theResult as! NSResponder?
            {
                theResult = theResponder.nextResponder
            }
            else
            {
                theResult = nil
            }
        }
        
        return theResult
    }

    func findRespondableObject(of key: String) -> NSObject?
    {
        var theResult: NSObject? = nil
        
        theResult = self.findRespondableObject(self, withKey: key)
        
        if theResult != nil
        {
            return theResult
        }

        theResult = self.findRespondableObject(NSApp, withKey: key)
        
        if theResult != nil
        {
            return theResult
        }

        theResult = self.findRespondableObject(NSDocumentController.shared, withKey: key)
        
        if theResult != nil
        {
            return theResult
        }
        
        return nil
    }

    
}
