/** @module other */

const EventEmitter = require('events')

/** @inheritdoc */
class Channel extends EventEmitter {
 // TODO: Implement me.
}

/** @inheritdoc */
class Account extends EventEmitter {
 // TODO: Implement me.
}

/** @inheritdoc */
class Identity extends EventEmitter {
  // TODO: Implement me.
}

/**
 * An interface for Features to interact with the chatternet.
 *
 * @inheritdoc
 */
class Chatternet extends EventEmitter {
  /**
   * @param {Object} args - destructured args.
   * @param {string} args.identity - Scope for chatternet interactions.
   */
  constructor({identity}) {
    super()
  }

  /** @return {Channel} The channel associated witht he given id or else null if it doesn't exist. */
  channel({id}) {
    return new Channel() // TODO: Implement me.
  }

  /** @return {Account} The account associated witht he given id or else null if it doesn't exist. */
  account({id}) {
    return new Account() // TODO: Implement me.
  }

  /** @return {Identity} The identity associated witht he given id or else null if it doesn't exist. */
  identity({id}) {
    return new Identity() // TODO: Implement me.
  }
}

/**
 * An interface for Features to interact with an Other Chat user agent.
 *
 * @inheritdoc
 */
class UserAgent extends EventEmitter {
  /** @return {Channel} The currently active channel. */
  channel() {
    return new Channel() // TODO: Implement me.
  }

  /** @return {Account} The currently active account. */
  account() {
    return new Account() // TODO: Implement me.
  }

  /** @return {Identity} The currently active identity. */
  identity() {
    return new Identity() // TODO: Implement me.
  }

  /**
   * Navigates to the given channel id.
   *
   * @param {Object} target - The navigation target.
   * @param {string} target.channelId - The channel identifier to navigate to. May be (1) identityId for identity channels (2) channelId for standard channels or (3) lowerIdentityId:upperIdentityId for whisper channels.
   */
  navigate({channelId}) {
    // TODO: Implement me.
  }
}

/**
 * An item which may be displayed as a chat complete result.
 */
class ChatCompleteResult {
  constructor({text}) {
    this.text = text
  }
}

/**
 * A command which users may run from the input area.
 *
 * TODO: Rationalize this in terms of a UserAgent input area onChange event.
 */
class Command {
  /**
   * @param {Object} args - destructured args.
   * @param {string[]} args.tokens - Keyword tokens which the user may type at the beginning of the input area to invoke this command.
   * @param {onQueryCallback} args.onQuery - Called when one of the tokens is invoked by the user.
   */
  constructor({tokens, onQuery}) {
    this._tokens = tokens
    this._onQuery = onQuery
  }

  get tokens() {
    return this._tokens
  }

  /** @param {onQueryCallback} callback - Called when one of the tokens is invoked by the user. */
  onQuery(callback) {
    this._onQuery = callback
    // TODO: Implement me.
  }

  /**
   * @callback onQueryCallback
   * @param {string} token - The token that was invoked.
   * @param {string} query - The user's query (i.e. all text entered after the token).
   * @param {Promise} promise - Resolve this with a list of ChatCompleteResults.
   */
}

/**
 * A package that extends Chatternet and/or Other Chat user agent functionality.
 * This is the base unit of other.js.
 */
class Feature {
  /**
   * @param {Object} metadata - metadata describing the package.
   * @param {string} metadata.name - User facing name.
   * @param {string} metadata.description - User facing, one-line description .
   * @param {string} metadata.version - {@link http://semver.org/|Semantic Version} used for determining compatibility with clients and other features.
   * @param {string} metadata.identity - Feature developer's Chatternet Identity under which all Chatternet operations are performed.
   * @param {Command[]} metadata.commands - Commands to register.
   */
  constructor({name, description, version, identity, commands = []}) {
    // TODO: Validation
    this.name = name
    this.description = description
    this.version = version
    this.identity = identity
    this.commands = commands
    this._chatternet = identity ? new Chatternet({identity}) : null
    this._userAgent = new UserAgent()

    console.log(`Created feature: ${name} ${version}`) // TODO: Remove.
  }

  /** @return {Chatternet} The global chatternet as seen by this feature's identity or null if the feature doesn't have access. */
  get chatternet() {
    return this._chatternet
  }

  /** @return {UserAgent} The user agent's current browsing context. */
  get userAgent() {
    return this._userAgent
  }
}

module.exports = {ChatCompleteResult, Command, Feature}

@@ -2677,25 +2677,24 @@
  %7B%0A    this.
-_
 tokens = tok
@@ -2734,54 +2734,8 @@
  %7D%0A%0A
-  get tokens() %7B%0A    return this._tokens%0A  %7D%0A%0A
   /*
@@ -4235,81 +4235,8 @@
 nt()
-%0A%0A    console.log(%60Created feature: $%7Bname%7D $%7Bversion%7D%60) // TODO: Remove.
 %0A  %7D

Make tokens public and remove stray log