//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

// Implementation note: NSIndexPath is an efficient array of integers for Objective-C.
// For Swift, we bridge to this wrapper of Array<Int>. This gives us great Swift performance and interop with Objective-C.

/**
 `IndexPath` represents the path to a specific node in a tree of nested array collections.
 
 Each index in an index path represents the index into an array of children from one node in the tree to another, deeper, node.
 */
public struct IndexPath : ReferenceConvertible, Equatable, Hashable, MutableCollection, RandomAccessCollection, Comparable, ExpressibleByArrayLiteral {
    public typealias ReferenceType = NSIndexPath
    public typealias Element = Int
    public typealias Index = Array<Int>.Index
    public typealias Indices = DefaultRandomAccessIndices<IndexPath>
    
    fileprivate var _indexes : Array<Int>
    
    /// Initialize an empty index path.
    public init() {
        _indexes = []
    }
    
    /// Initialize with a sequence of integers.
    public init<ElementSequence : Sequence>(indexes: ElementSequence)
        where ElementSequence.Iterator.Element == Element {
            _indexes = indexes.map { $0 }
    }
    
    /// Initialize with an array literal.
    public init(arrayLiteral indexes: Element...) {
        _indexes = indexes
    }
    
    /// Initialize with an array of elements.
    public init(indexes: [Element]) {
        _indexes = indexes
    }
    
    /// Initialize with a single element.
    public init(index: Element) {
        _indexes = [index]
    }
    
    /// Return a new `IndexPath` containing all but the last element.
    public func dropLast() -> IndexPath {
        return IndexPath(indexes: _indexes.dropLast())
    }
    
    /// Append an `IndexPath` to `self`.
    public mutating func append(_ other: IndexPath) {
        _indexes.append(contentsOf: other._indexes)
    }
    
    /// Append a single element to `self`.
    public mutating func append(_ other: Element) {
        _indexes.append(other)
    }
    
    /// Append an array of elements to `self`.
    public mutating func append(_ other: [Element]) {
        _indexes.append(contentsOf: other)
    }
    
    /// Return a new `IndexPath` containing the elements in self and the elements in `other`.
    public func appending(_ other: Element) -> IndexPath {
        var result = _indexes
        result.append(other)
        return IndexPath(indexes: result)
    }
    
    /// Return a new `IndexPath` containing the elements in self and the elements in `other`.
    public func appending(_ other: IndexPath) -> IndexPath {
        return IndexPath(indexes: _indexes + other._indexes)
    }
    
    /// Return a new `IndexPath` containing the elements in self and the elements in `other`.
    public func appending(_ other: [Element]) -> IndexPath {
        return IndexPath(indexes: _indexes + other)
    }
    
    public subscript(index: Index) -> Element {
        get {
            return _indexes[index]
        }
        set {
            _indexes[index] = newValue
        }
    }
    
    public subscript(range: Range<Index>) -> IndexPath {
        get {
            return IndexPath(indexes: _indexes[range])
        }
        set {
            _indexes.replaceSubrange(range, with: newValue._indexes)
        }
    }
    
    public func makeIterator() -> IndexingIterator<IndexPath> {
        return IndexingIterator(_elements: self)
    }
    
    public var count: Int {
        return _indexes.count
    }
    
    public var startIndex: Index {
        return _indexes.startIndex
    }
    
    public var endIndex: Index {
        return _indexes.endIndex
    }
    
    public func index(before i: Index) -> Index {
        return _indexes.index(before: i)
    }
    
    public func index(after i: Index) -> Index {
        return _indexes.index(after: i)
    }
    
    /// Sorting an array of `IndexPath` using this comparison results in an array representing nodes in depth-first traversal order.
    public func compare(_ other: IndexPath) -> ComparisonResult {
        // This is temporary
        let me = self.makeReference()
        let other = other.makeReference()
        return me.compare(IndexPath._unconditionallyBridgeFromObjectiveC(other))
    }
    
    public var hashValue: Int {
        // This is temporary
        let me = self.makeReference()
        return me.hash
    }
    
    // MARK: - Bridging Helpers
    
    fileprivate init(nsIndexPath: ReferenceType) {
        let count = nsIndexPath.length
        if count == 0 {
            _indexes = []
        } else {
            var ptr = malloc(count * MemoryLayout<Element>.size)
            defer { free(ptr) }
            
            let elementPtr = ptr!.bindMemory(to: Element.self, capacity: count)
            nsIndexPath.getIndexes(elementPtr, range: NSMakeRange(0, count))
            
            let buffer = UnsafeBufferPointer(start: elementPtr, count: count)
            _indexes = buffer.map { $0 }
        }
    }
    
    fileprivate func makeReference() -> ReferenceType {
        return _indexes.withUnsafeBufferPointer {
            return ReferenceType(indexes: $0.baseAddress, length: $0.count)
        }
    }
    
    public static func ==(lhs: IndexPath, rhs: IndexPath) -> Bool {
        return lhs._indexes == rhs._indexes
    }

    public static func +(lhs: IndexPath, rhs: IndexPath) -> IndexPath {
        return lhs.appending(rhs)
    }

    public static func +=(lhs: inout IndexPath, rhs: IndexPath) {
        lhs.append(rhs)
    }

    public static func <(lhs: IndexPath, rhs: IndexPath) -> Bool {
        return lhs.compare(rhs) == ComparisonResult.orderedAscending
    }

    public static func <=(lhs: IndexPath, rhs: IndexPath) -> Bool {
        let order = lhs.compare(rhs)
        return order == ComparisonResult.orderedAscending || order == ComparisonResult.orderedSame
    }

    public static func >(lhs: IndexPath, rhs: IndexPath) -> Bool {
        return lhs.compare(rhs) == ComparisonResult.orderedDescending
    }

    public static func >=(lhs: IndexPath, rhs: IndexPath) -> Bool {
        let order = lhs.compare(rhs)
        return order == ComparisonResult.orderedDescending || order == ComparisonResult.orderedSame
    }
}

extension IndexPath : CustomStringConvertible, CustomDebugStringConvertible, CustomReflectable {
    public var description: String {
        return _indexes.description
    }

    public var debugDescription: String {
        return _indexes.debugDescription
    }
    
    public var customMirror: Mirror {
        return _indexes.customMirror
    }
}

extension IndexPath : _ObjectTypeBridgeable {
    public static func _getObjectiveCType() -> Any.Type {
        return NSIndexPath.self
    }
    
    @_semantics("convertToObjectiveC")
    public func _bridgeToObjectiveC() -> NSIndexPath {
        return makeReference()
    }
    
    public static func _forceBridgeFromObjectiveC(_ x: NSIndexPath, result: inout IndexPath?) {
        result = IndexPath(nsIndexPath: x)
    }
    
    public static func _conditionallyBridgeFromObjectiveC(_ x: NSIndexPath, result: inout IndexPath?) -> Bool {
        result = IndexPath(nsIndexPath: x)
        return true
    }
    
    public static func _unconditionallyBridgeFromObjectiveC(_ source: NSIndexPath?) -> IndexPath {
        return IndexPath(nsIndexPath: source!)
    }
}

extension NSIndexPath : _HasCustomAnyHashableRepresentation {
    // Must be @nonobjc to avoid infinite recursion during bridging.
    @nonobjc
    public func _toCustomAnyHashable() -> AnyHashable? {
        return AnyHashable(IndexPath._unconditionallyBridgeFromObjectiveC(self))
    }
}
