//===-------------------- Syntax.swift - Syntax Protocol ------------------===//
//
// This source file is part of the Swift.org open source project
//
// 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
//
//===----------------------------------------------------------------------===//

import Foundation

/// A Syntax node represents a tree of nodes with tokens at the leaves.
/// Each node has accessors for its known children, and allows efficient
/// iteration over the children through its `children` property.
public class Syntax: CustomStringConvertible {
  /// The type of sequence containing the indices of present children.
  internal typealias PresentChildIndicesSequence =
    LazyFilterSequence<CountableRange<Int>>

  /// The root of the tree this node is currently in.
  internal let _root: SyntaxData
  
  /// The data backing this node.
  /// - note: This is unowned, because the reference to the root data keeps it
  ///         alive. This means there is an implicit relationship -- the data
  ///         property must be a descendent of the root. This relationship must
  ///         be preserved in all circumstances where Syntax nodes are created.
  internal unowned var data: SyntaxData

#if DEBUG
  func validate() {
    // This is for subclasses to override to perform structural validation.
  }
#endif

  /// Creates a Syntax node from the provided root and data.
  internal init(root: SyntaxData, data: SyntaxData) {
    self._root = root
    self.data = data
#if DEBUG
    validate()
#endif
  }

  /// Access the raw syntax assuming the node is a Syntax.
  var raw: RawSyntax {
    return data.raw
  }

  /// An iterator over children of this node.
  public var children: SyntaxChildren {
    return SyntaxChildren(node: self)
  }

  /// Whether or not this node it marked as `present`.
  public var isPresent: Bool {
    return raw.presence == .present
  }

  /// Whether or not this node it marked as `missing`.
  public var isMissing: Bool {
    return raw.presence == .missing
  }

  /// Whether or not this node represents an Expression.
  public var isExpr: Bool {
    return raw.kind.isExpr
  }
  
  /// Whether or not this node represents a Declaration.
  public var isDecl: Bool {
    return raw.kind.isDecl
  }

  /// Whether or not this node represents a Statement.
  public var isStmt: Bool {
    return raw.kind.isStmt
  }

  /// Whether or not this node represents a Type.
  public var isType: Bool {
    return raw.kind.isType
  }

  /// Whether or not this node represents a Pattern.
  public var isPattern: Bool {
    return raw.kind.isPattern
  }

  /// The parent of this syntax node, or `nil` if this node is the root.
  public var parent: Syntax? {
    guard let parentData = data.parent else { return nil }
    return Syntax.make(root: _root, data: parentData)
  }

  /// The index of this node in the parent's children.
  public var indexInParent: Int {
    return data.indexInParent
  }

  /// The root of the tree in which this node resides.
  public var root: Syntax {
    return Syntax.make(root: _root,  data: _root)
  }
  
  /// The sequence of indices that correspond to child nodes that are not
  /// missing.
  ///
  /// This property is an implementation detail of `SyntaxChildren`.
  internal var presentChildIndices: PresentChildIndicesSequence {
    return raw.layout.indices.lazy.filter { self.raw.layout[$0].isPresent }
  }

  /// Gets the child at the provided index in this node's children.
  /// - Parameter index: The index of the child node you're looking for.
  /// - Returns: A Syntax node for the provided child, or `nil` if there
  ///            is not a child at that index in the node.
  public func child(at index: Int) -> Syntax? {
    guard raw.layout.indices.contains(index) else { return nil }
    if raw.layout[index].isMissing { return nil }
    return Syntax.make(root: _root, data: data.cachedChild(at: index))
  }

  /// A source-accurate description of this node.
  public var description: String {
    var s = ""
    self.write(to: &s)
    return s
  }
}

extension Syntax: TextOutputStreamable {
  /// Prints the raw value of this node to the provided stream.
  /// - Parameter stream: The stream to which to print the raw tree.
  public func write<Target>(to target: inout Target)
    where Target: TextOutputStream {
    data.raw.write(to: &target)
  }
}

extension Syntax: Equatable {
  /// Determines if two nodes are equal to each other.
  public static func ==(lhs: Syntax, rhs: Syntax) -> Bool {
    return lhs.data === rhs.data
  }
}

/// MARK: - Nodes

/// A Syntax node representing a single token.
public class TokenSyntax: Syntax {
  /// The text of the token as written in the source code.
  public var text: String {
    return tokenKind.text
  }

  public func withKind(_ tokenKind: TokenKind) -> TokenSyntax {
    guard case let .token(_, leadingTrivia, trailingTrivia, presence) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    let (root, newData) = data.replacingSelf(.token(tokenKind, leadingTrivia,
                                                    trailingTrivia, presence))
    return TokenSyntax(root: root, data: newData)
  }

  /// Returns a new TokenSyntax with its leading trivia replaced
  /// by the provided trivia.
  public func withLeadingTrivia(_ leadingTrivia: Trivia) -> TokenSyntax {
    guard case let .token(kind, _, trailingTrivia, presence) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    let (root, newData) = data.replacingSelf(.token(kind, leadingTrivia,
                                                    trailingTrivia, presence))
    return TokenSyntax(root: root, data: newData)
  }

  /// Returns a new TokenSyntax with its trailing trivia replaced
  /// by the provided trivia.
  public func withTrailingTrivia(_ trailingTrivia: Trivia) -> TokenSyntax {
    guard case let .token(kind, leadingTrivia, _, presence) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    let (root, newData) = data.replacingSelf(.token(kind, leadingTrivia,
                                                    trailingTrivia, presence))
    return TokenSyntax(root: root, data: newData)
  }

  /// Returns a new TokenSyntax with its leading trivia removed.
  public func withoutLeadingTrivia() -> TokenSyntax {
    return withLeadingTrivia([])
  }

  /// Returns a new TokenSyntax with its trailing trivia removed.
  public func withoutTrailingTrivia() -> TokenSyntax {
    return withTrailingTrivia([])
  }

  /// Returns a new TokenSyntax with all trivia removed.
  public func withoutTrivia() -> TokenSyntax {
    return withoutLeadingTrivia().withoutTrailingTrivia()
  }

  /// The leading trivia (spaces, newlines, etc.) associated with this token.
  public var leadingTrivia: Trivia {
    guard case .token(_, let leadingTrivia, _, _) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    return leadingTrivia
  }

  /// The trailing trivia (spaces, newlines, etc.) associated with this token.
  public var trailingTrivia: Trivia {
    guard case .token(_, _, let trailingTrivia, _) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    return trailingTrivia
  }

  /// The kind of token this node represents.
  public var tokenKind: TokenKind {
    guard case .token(let kind, _, _, _) = raw else {
      fatalError("TokenSyntax must have token as its raw")
    }
    return kind
  }
}
