import AtRule = require('./at-rule.js')

import { AtRuleProps } from './at-rule.js'
import Comment, { CommentProps } from './comment.js'
import Container from './container.js'
import CssSyntaxError from './css-syntax-error.js'
import Declaration, { DeclarationProps } from './declaration.js'
import Document from './document.js'
import Input from './input.js'
import { Stringifier, Syntax } from './postcss.js'
import Result from './result.js'
import Root from './root.js'
import Rule, { RuleProps } from './rule.js'
import Warning, { WarningOptions } from './warning.js'

declare namespace Node {
  export type ChildNode = AtRule.default | Comment | Declaration | Rule

  export type AnyNode =
    | AtRule.default
    | Comment
    | Declaration
    | Document
    | Root
    | Rule

  export type ChildProps =
    | AtRuleProps
    | CommentProps
    | DeclarationProps
    | RuleProps

  export interface Position {
    /**
     * Source line in file. In contrast to `offset` it starts from 1.
     */
    column: number

    /**
     * Source column in file.
     */
    line: number

    /**
     * Source offset in file. It starts from 0.
     */
    offset: number
  }

  export interface Range {
    /**
     * End position, exclusive.
     */
    end: Position

    /**
     * Start position, inclusive.
     */
    start: Position
  }

  /**
   * Source represents an interface for the {@link Node.source} property.
   */
  export interface Source {
    /**
     * The inclusive ending position for the source
     * code of a node.
     */
    end?: Position

    /**
     * The source file from where a node has originated.
     */
    input: Input

    /**
     * The inclusive starting position for the source
     * code of a node.
     */
    start?: Position
  }

  /**
   * Interface represents an interface for an object received
   * as parameter by Node class constructor.
   */
  export interface NodeProps {
    source?: Source
  }

  export interface NodeErrorOptions {
    /**
     * An ending index inside a node's string that should be highlighted as
     * source of error.
     */
    endIndex?: number
    /**
     * An index inside a node's string that should be highlighted as source
     * of error.
     */
    index?: number
    /**
     * Plugin name that created this error. PostCSS will set it automatically.
     */
    plugin?: string
    /**
     * A word inside a node's string, that should be highlighted as source
     * of error.
     */
    word?: string
  }

  // eslint-disable-next-line @typescript-eslint/no-shadow
  class Node extends Node_ {}
  export { Node as default }
}

/**
 * It represents an abstract class that handles common
 * methods for other CSS abstract syntax tree nodes.
 *
 * Any node that represents CSS selector or value should
 * not extend the `Node` class.
 */
declare abstract class Node_ {
  /**
   * It represents parent of the current node.
   *
   * ```js
   * root.nodes[0].parent === root //=> true
   * ```
   */
  parent: Container | Document | undefined

  /**
   * It represents unnecessary whitespace and characters present
   * in the css source code.
   *
   * Information to generate byte-to-byte equal node string as it was
   * in the origin input.
   *
   * The properties of the raws object are decided by parser,
   * the default parser uses the following properties:
   *
   * * `before`: the space symbols before the node. It also stores `*`
   *   and `_` symbols before the declaration (IE hack).
   * * `after`: the space symbols after the last child of the node
   *   to the end of the node.
   * * `between`: the symbols between the property and value
   *   for declarations, selector and `{` for rules, or last parameter
   *   and `{` for at-rules.
   * * `semicolon`: contains true if the last child has
   *   an (optional) semicolon.
   * * `afterName`: the space between the at-rule name and its parameters.
   * * `left`: the space symbols between `/*` and the comment’s text.
   * * `right`: the space symbols between the comment’s text
   *   and <code>*&#47;</code>.
   * - `important`: the content of the important statement,
   *   if it is not just `!important`.
   *
   * PostCSS filters out the comments inside selectors, declaration values
   * and at-rule parameters but it stores the origin content in raws.
   *
   * ```js
   * const root = postcss.parse('a {\n  color:black\n}')
   * root.first.first.raws //=> { before: '\n  ', between: ':' }
   * ```
   */
  raws: any

  /**
   * It represents information related to origin of a node and is required
   * for generating source maps.
   *
   * The nodes that are created manually using the public APIs
   * provided by PostCSS will have `source` undefined and
   * will be absent in the source map.
   *
   * For this reason, the plugin developer should consider
   * duplicating nodes as the duplicate node will have the
   * same source as the original node by default or assign
   * source to a node created manually.
   *
   * ```js
   * decl.source.input.from //=> '/home/ai/source.css'
   * decl.source.start      //=> { line: 10, column: 2 }
   * decl.source.end        //=> { line: 10, column: 12 }
   * ```
   *
   * ```js
   * // Incorrect method, source not specified!
   * const prefixed = postcss.decl({
   *   prop: '-moz-' + decl.prop,
   *   value: decl.value
   * })
   *
   * // Correct method, source is inherited when duplicating.
   * const prefixed = decl.clone({
   *   prop: '-moz-' + decl.prop
   * })
   * ```
   *
   * ```js
   * if (atrule.name === 'add-link') {
   *   const rule = postcss.rule({
   *     selector: 'a',
   *     source: atrule.source
   *   })
   *
   *  atrule.parent.insertBefore(atrule, rule)
   * }
   * ```
   */
  source?: Node.Source

  /**
   * It represents type of a node in
   * an abstract syntax tree.
   *
   * A type of node helps in identification of a node
   * and perform operation based on it's type.
   *
   * ```js
   * const declaration = new Declaration({
   *   prop: 'color',
   *   value: 'black'
   * })
   *
   * declaration.type //=> 'decl'
   * ```
   */
  type: string

  constructor(defaults?: object)

  /**
   * Insert new node after current node to current node’s parent.
   *
   * Just alias for `node.parent.insertAfter(node, add)`.
   *
   * ```js
   * decl.after('color: black')
   * ```
   *
   * @param newNode New node.
   * @return This node for methods chain.
   */
  after(newNode: Node | Node.ChildProps | Node[] | string | undefined): this

  /**
   * It assigns properties to an existing node instance.
   *
   * ```js
   * decl.assign({ prop: 'word-wrap', value: 'break-word' })
   * ```
   *
   * @param overrides New properties to override the node.
   *
   * @return `this` for method chaining.
   */
  assign(overrides: object): this

  /**
   * Insert new node before current node to current node’s parent.
   *
   * Just alias for `node.parent.insertBefore(node, add)`.
   *
   * ```js
   * decl.before('content: ""')
   * ```
   *
   * @param newNode New node.
   * @return This node for methods chain.
   */
  before(newNode: Node | Node.ChildProps | Node[] | string | undefined): this

  /**
   * Clear the code style properties for the node and its children.
   *
   * ```js
   * node.raws.before  //=> ' '
   * node.cleanRaws()
   * node.raws.before  //=> undefined
   * ```
   *
   * @param keepBetween Keep the `raws.between` symbols.
   */
  cleanRaws(keepBetween?: boolean): void

  /**
   * It creates clone of an existing node, which includes all the properties
   * and their values, that includes `raws` but not `type`.
   *
   * ```js
   * decl.raws.before    //=> "\n  "
   * const cloned = decl.clone({ prop: '-moz-' + decl.prop })
   * cloned.raws.before  //=> "\n  "
   * cloned.toString()   //=> -moz-transform: scale(0)
   * ```
   *
   * @param overrides New properties to override in the clone.
   *
   * @return Duplicate of the node instance.
   */
  clone(overrides?: object): Node

  /**
   * Shortcut to clone the node and insert the resulting cloned node
   * after the current node.
   *
   * @param overrides New properties to override in the clone.
   * @return New node.
   */
  cloneAfter(overrides?: object): Node

  /**
   * Shortcut to clone the node and insert the resulting cloned node
   * before the current node.
   *
   * ```js
   * decl.cloneBefore({ prop: '-moz-' + decl.prop })
   * ```
   *
   * @param overrides Mew properties to override in the clone.
   *
   * @return New node
   */
  cloneBefore(overrides?: object): Node

  /**
   * It creates an instance of the class `CssSyntaxError` and parameters passed
   * to this method are assigned to the error instance.
   *
   * The error instance will have description for the
   * error, original position of the node in the
   * source, showing line and column number.
   *
   * If any previous map is present, it would be used
   * to get original position of the source.
   *
   * The Previous Map here is referred to the source map
   * generated by previous compilation, example: Less,
   * Stylus and Sass.
   *
   * This method returns the error instance instead of
   * throwing it.
   *
   * ```js
   * if (!variables[name]) {
   *   throw decl.error(`Unknown variable ${name}`, { word: name })
   *   // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black
   *   //   color: $black
   *   // a
   *   //          ^
   *   //   background: white
   * }
   * ```
   *
   * @param message Description for the error instance.
   * @param options Options for the error instance.
   *
   * @return Error instance is returned.
   */
  error(message: string, options?: Node.NodeErrorOptions): CssSyntaxError

  /**
   * Returns the next child of the node’s parent.
   * Returns `undefined` if the current node is the last child.
   *
   * ```js
   * if (comment.text === 'delete next') {
   *   const next = comment.next()
   *   if (next) {
   *     next.remove()
   *   }
   * }
   * ```
   *
   * @return Next node.
   */
  next(): Node.ChildNode | undefined

  /**
   * Get the position for a word or an index inside the node.
   *
   * @param opts Options.
   * @return Position.
   */
  positionBy(opts?: Pick<WarningOptions, 'index' | 'word'>): Node.Position

  /**
   * Convert string index to line/column.
   *
   * @param index The symbol number in the node’s string.
   * @return Symbol position in file.
   */
  positionInside(index: number): Node.Position

  /**
   * Returns the previous child of the node’s parent.
   * Returns `undefined` if the current node is the first child.
   *
   * ```js
   * const annotation = decl.prev()
   * if (annotation.type === 'comment') {
   *   readAnnotation(annotation.text)
   * }
   * ```
   *
   * @return Previous node.
   */
  prev(): Node.ChildNode | undefined

  /**
   * Get the range for a word or start and end index inside the node.
   * The start index is inclusive; the end index is exclusive.
   *
   * @param opts Options.
   * @return Range.
   */
  rangeBy(
    opts?: Pick<WarningOptions, 'endIndex' | 'index' | 'word'>
  ): Node.Range

  /**
   * Returns a `raws` value. If the node is missing
   * the code style property (because the node was manually built or cloned),
   * PostCSS will try to autodetect the code style property by looking
   * at other nodes in the tree.
   *
   * ```js
   * const root = postcss.parse('a { background: white }')
   * root.nodes[0].append({ prop: 'color', value: 'black' })
   * root.nodes[0].nodes[1].raws.before   //=> undefined
   * root.nodes[0].nodes[1].raw('before') //=> ' '
   * ```
   *
   * @param prop        Name of code style property.
   * @param defaultType Name of default value, it can be missed
   *                    if the value is the same as prop.
   * @return {string} Code style value.
   */
  raw(prop: string, defaultType?: string): string

  /**
   * It removes the node from its parent and deletes its parent property.
   *
   * ```js
   * if (decl.prop.match(/^-webkit-/)) {
   *   decl.remove()
   * }
   * ```
   *
   * @return `this` for method chaining.
   */
  remove(): this

  /**
   * Inserts node(s) before the current node and removes the current node.
   *
   * ```js
   * AtRule: {
   *   mixin: atrule => {
   *     atrule.replaceWith(mixinRules[atrule.params])
   *   }
   * }
   * ```
   *
   * @param nodes Mode(s) to replace current one.
   * @return Current node to methods chain.
   */
  replaceWith(
    ...nodes: (
      | Node.ChildNode
      | Node.ChildNode[]
      | Node.ChildProps
      | Node.ChildProps[]
    )[]
  ): this

  /**
   * Finds the Root instance of the node’s tree.
   *
   * ```js
   * root.nodes[0].nodes[0].root() === root
   * ```
   *
   * @return Root parent.
   */
  root(): Root

  /**
   * Fix circular links on `JSON.stringify()`.
   *
   * @return Cleaned object.
   */
  toJSON(): object

  /**
   * It compiles the node to browser readable cascading style sheets string
   * depending on it's type.
   *
   * ```js
   * new Rule({ selector: 'a' }).toString() //=> "a {}"
   * ```
   *
   * @param stringifier A syntax to use in string generation.
   * @return CSS string of this node.
   */
  toString(stringifier?: Stringifier | Syntax): string

  /**
   * It is a wrapper for {@link Result#warn}, providing convenient
   * way of generating warnings.
   *
   * ```js
   *   Declaration: {
   *     bad: (decl, { result }) => {
   *       decl.warn(result, 'Deprecated property: bad')
   *     }
   *   }
   * ```
   *
   * @param result The `Result` instance that will receive the warning.
   * @param message Description for the warning.
   * @param options Options for the warning.
   *
   * @return `Warning` instance is returned
   */
  warn(result: Result, message: string, options?: WarningOptions): Warning
}

declare class Node extends Node_ {}

export = Node
