// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop

import Foundation

#if FOUNDATION_XCTEST
import XCTest
class TestUserInfoSuper : XCTestCase { }
#else
import StdlibUnittest
class TestUserInfoSuper : NSObject { }
#endif

struct SubStruct: Equatable {
    var i: Int
    var str: String

    static func ==(lhs: SubStruct, rhs: SubStruct) -> Bool {
        return lhs.i == rhs.i && 
               lhs.str == rhs.str
    }
}

struct SomeStructure: Hashable {
    var i: Int
    var str: String
    var sub: SubStruct

    static func ==(lhs: SomeStructure, rhs: SomeStructure) -> Bool {
        return lhs.i == rhs.i && 
               lhs.str == rhs.str && 
               lhs.sub == rhs.sub
    }

    // FIXME: we don't care about this, but Any only finds == on Hashables
    func hash(into hasher: inout Hasher) {
        hasher.combine(i)
        hasher.combine(str)
        hasher.combine(sub.i)
        hasher.combine(sub.str)
    }
}

/*
 Notification and potentially other structures require a representation of a 
 userInfo dictionary. The Objective-C counterparts are represented via
 NSDictionary which can only store a hashable key (actually 
 NSObject<NSCopying> *) and a value of AnyObject (actually NSObject *). However
 it is desired in swift to store Any in the value. These structure expositions
 in swift have an adapter that allows them to pass a specialized NSDictionary
 subclass to the Objective-C layer that can round trip the stored Any types back
 out into Swift.

 In this case NSNotification -> Notification bridging is suitable to verify that
 behavior.
*/

class TestUserInfo : TestUserInfoSuper {
    var posted: Notification?

    func validate(_ testStructure: SomeStructure, _ value: SomeStructure) {
        expectEqual(testStructure.i, value.i)
        expectEqual(testStructure.str, value.str)
        expectEqual(testStructure.sub.i, value.sub.i)
        expectEqual(testStructure.sub.str, value.sub.str)
    }

    func test_userInfoPost() {
        let userInfoKey = "userInfoKey"
        let notifName = Notification.Name(rawValue: "TestSwiftNotification")
        let testStructure = SomeStructure(i: 5, str: "10", sub: SubStruct(i: 6, str: "11"))
        let info: [AnyHashable : Any] = [
            AnyHashable(userInfoKey) : testStructure
        ]
        let note = Notification(name: notifName, userInfo: info)
        expectNotNil(note.userInfo)
        let nc = NotificationCenter.default
        nc.addObserver(self, selector: #selector(TestUserInfo.notification(_:)), name: notifName, object: nil)
        nc.post(note)
        expectNotNil(posted)
        if let notification = posted {
            let postedInfo = notification.userInfo
            expectNotNil(postedInfo)
            if let userInfo = postedInfo {
                let postedValue = userInfo[AnyHashable(userInfoKey)] as? SomeStructure
                expectNotNil(postedValue)
                if let value = postedValue {
                    validate(testStructure, value)
                }
            }
        }
    }

    func test_equality() {
        let userInfoKey = "userInfoKey"
        let notifName = Notification.Name(rawValue: "TestSwiftNotification")
        let testStructure = SomeStructure(i: 5, str: "10", sub: SubStruct(i: 6, str: "11"))
        let testStructure2 = SomeStructure(i: 6, str: "10", sub: SubStruct(i: 6, str: "11"))
        let info1: [AnyHashable : Any] = [
            AnyHashable(userInfoKey) : testStructure
        ]
        let info2: [AnyHashable : Any] = [
            AnyHashable(userInfoKey) : "this can convert"
        ]
        let info3: [AnyHashable : Any] = [
            AnyHashable(userInfoKey) : testStructure2
        ]

        let note1 = Notification(name: notifName, userInfo: info1)
        let note2 = Notification(name: notifName, userInfo: info1)
        expectEqual(note1, note2)

        let note3 = Notification(name: notifName, userInfo: info2)
        let note4 = Notification(name: notifName, userInfo: info2)
        expectEqual(note3, note4)

        let note5 = Notification(name: notifName, userInfo: info3)
        expectNotEqual(note1, note5)
    }

    @objc func notification(_ notif: Notification) {
        posted = notif
    }

    // MARK: -
    func test_classForCoder() {
        // confirm internal bridged impl types are not exposed to archival machinery
        // we have to be circuitous here, as bridging makes it very difficult to confirm this
        //
        // Gated on the availability of NSKeyedArchiver.archivedData(withRootObject:).
        if #available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *) {
            let note = Notification(name: Notification.Name(rawValue: "TestSwiftNotification"), userInfo: [AnyHashable("key"):"value"])
            let archivedNote = NSKeyedArchiver.archivedData(withRootObject: note)
            let noteAsPlist = try! PropertyListSerialization.propertyList(from: archivedNote, options: [], format: nil)
            let plistAsData = try! PropertyListSerialization.data(fromPropertyList: noteAsPlist, format: .xml, options: 0)
            let xml = NSString(data: plistAsData, encoding: String.Encoding.utf8.rawValue)!
            expectEqual(xml.range(of: "_NSUserInfoDictionary").location, NSNotFound)
        }
    }

    func test_AnyHashableContainingNotification() {
        let values: [Notification] = [
            Notification(name: Notification.Name(rawValue: "TestSwiftNotification")),
            Notification(name: Notification.Name(rawValue: "TestOtherSwiftNotification")),
            Notification(name: Notification.Name(rawValue: "TestOtherSwiftNotification")),
        ]
        let anyHashables = values.map(AnyHashable.init)
        expectEqual(Notification.self, type(of: anyHashables[0].base))
        expectEqual(Notification.self, type(of: anyHashables[1].base))
        expectEqual(Notification.self, type(of: anyHashables[2].base))
        expectNotEqual(anyHashables[0], anyHashables[1])
        expectEqual(anyHashables[1], anyHashables[2])
    }

    func test_AnyHashableCreatedFromNSNotification() {
        let values: [NSNotification] = [
            NSNotification(name: Notification.Name(rawValue: "TestSwiftNotification"), object: nil),
            NSNotification(name: Notification.Name(rawValue: "TestOtherSwiftNotification"), object: nil),
            NSNotification(name: Notification.Name(rawValue: "TestOtherSwiftNotification"), object: nil),
        ]
        let anyHashables = values.map(AnyHashable.init)
        expectEqual(Notification.self, type(of: anyHashables[0].base))
        expectEqual(Notification.self, type(of: anyHashables[1].base))
        expectEqual(Notification.self, type(of: anyHashables[2].base))
        expectNotEqual(anyHashables[0], anyHashables[1])
        expectEqual(anyHashables[1], anyHashables[2])
    }
}

#if !FOUNDATION_XCTEST
var UserInfoTests = TestSuite("UserInfo")
UserInfoTests.test("test_userInfoPost") { TestUserInfo().test_userInfoPost() }
UserInfoTests.test("test_equality") { TestUserInfo().test_equality() }
UserInfoTests.test("test_classForCoder") { TestUserInfo().test_classForCoder() }
UserInfoTests.test("test_AnyHashableContainingNotification") { TestUserInfo().test_AnyHashableContainingNotification() }
UserInfoTests.test("test_AnyHashableCreatedFromNSNotification") { TestUserInfo().test_AnyHashableCreatedFromNSNotification() }
runAllTests()
#endif
