"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = exports.EventData = void 0;

var _util = require("@polkadot/util");

var _create = require("../../codec/create");

var _Struct = _interopRequireDefault(require("../../codec/Struct"));

var _Tuple = _interopRequireDefault(require("../../codec/Tuple"));

var _Null = _interopRequireDefault(require("../Null"));

// Copyright 2017-2019 @polkadot/types authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
const EventTypes = {};
/**
 * @name EventData
 * @description
 * Wrapper for the actual data that forms part of an [[Event]]
 */

class EventData extends _Tuple.default {
  constructor(Types, value, typeDef, meta, section, method) {
    super(Types, value);
    this._meta = void 0;
    this._method = void 0;
    this._section = void 0;
    this._typeDef = void 0;
    this._meta = meta;
    this._method = method;
    this._section = section;
    this._typeDef = typeDef;
  }
  /**
   * @description The wrapped [[EventMetadata]]
   */


  get meta() {
    return this._meta;
  }
  /**
   * @description The method as a string
   */


  get method() {
    return this._method;
  }
  /**
   * @description The section as a string
   */


  get section() {
    return this._section;
  }
  /**
   * @description The [[TypeDef]] for this event
   */


  get typeDef() {
    return this._typeDef;
  }

}
/**
 * @name Event
 * @description
 * A representation of a system event. These are generated via the [[Metadata]] interfaces and
 * specific to a specific Substrate runtime
 */


exports.EventData = EventData;

class Event extends _Struct.default {
  // Currently we _only_ decode from Uint8Array, since we expect it to
  // be used via EventRecord
  constructor(_value) {
    const {
      DataType,
      value
    } = Event.decodeEvent(_value);
    super({
      index: 'EventId',
      data: DataType
    }, value);
  }

  static decodeEvent() {
    let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Uint8Array();

    if (!value.length) {
      return {
        DataType: _Null.default
      };
    }

    const index = value.subarray(0, 2);
    const DataType = EventTypes[index.toString()];
    (0, _util.assert)(!(0, _util.isUndefined)(DataType), "Unable to decode ".concat((0, _util.u8aToHex)(index)));
    return {
      DataType,
      value: {
        index,
        data: value.subarray(2)
      }
    };
  } // This is called/injected by the API on init, allowing a snapshot of
  // the available system events to be used in lookups


  static injectMetadata(metadata) {
    metadata.asLatest.modules.filter((_ref) => {
      let {
        events
      } = _ref;
      return events.isSome;
    }).forEach((section, sectionIndex) => {
      const sectionName = (0, _util.stringCamelCase)(section.name.toString());
      section.events.unwrap().forEach((meta, methodIndex) => {
        const methodName = meta.name.toString();
        const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
        const typeDef = meta.args.map(arg => (0, _create.getTypeDef)(arg.toString()));
        const Types = typeDef.map(typeDef => (0, _create.getTypeClass)(typeDef));
        EventTypes[eventIndex.toString()] = class extends EventData {
          constructor(value) {
            super(Types, value, typeDef, meta, sectionName, methodName);
          }

        };
      });
    });
  }
  /**
   * @description The wrapped [[EventData]]
   */


  get data() {
    return this.get('data');
  }
  /**
   * @description The [[EventId]], identifying the raw event
   */


  get index() {
    return this.get('index');
  }
  /**
   * @description The [[EventMetadata]] with the documentation
   */


  get meta() {
    return this.data.meta;
  }
  /**
   * @description The method string identifying the event
   */


  get method() {
    return this.data.method;
  }
  /**
   * @description The section string identifying the event
   */


  get section() {
    return this.data.section;
  }
  /**
   * @description The [[TypeDef]] for the event
   */


  get typeDef() {
    return this.data.typeDef;
  }

}

exports.default = Event;