"use strict";

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

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

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

var _utilCrypto = require("@polkadot/util-crypto");

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

var _Base = _interopRequireDefault(require("../../codec/Base"));

var _AccountId = _interopRequireDefault(require("./AccountId"));

var _AccountIndex = _interopRequireDefault(require("./AccountIndex"));

// 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 ACCOUNT_ID_PREFIX = new Uint8Array([0xff]);
/**
 * @name Address
 * @description
 * A wrapper around an AccountId and/or AccountIndex that is encoded with a prefix.
 * Since we are dealing with underlying publicKeys (or shorter encoded addresses),
 * we extend from Base with an AccountId/AccountIndex wrapper. Basically the Address
 * is encoded as `[ <prefix-byte>, ...publicKey/...bytes ]` as per spec
 */

exports.ACCOUNT_ID_PREFIX = ACCOUNT_ID_PREFIX;

class Address extends _Base.default {
  constructor() {
    let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new Uint8Array();
    super(Address.decodeAddress(value));
  }

  static decodeAddress(value) {
    if (value instanceof _AccountId.default || value instanceof _AccountIndex.default) {
      return value;
    } else if (value instanceof Address) {
      return value.raw;
    } else if ((0, _util.isBn)(value) || (0, _util.isNumber)(value)) {
      return (0, _create.createType)('AccountIndex', value);
    } else if (Array.isArray(value) || (0, _util.isHex)(value) || (0, _util.isU8a)(value)) {
      return Address.decodeU8a((0, _util.u8aToU8a)(value));
    }

    return Address.decodeString(value);
  }

  static decodeString(value) {
    const decoded = (0, _utilCrypto.decodeAddress)(value);
    return decoded.length === 32 ? (0, _create.createType)('AccountId', decoded) : (0, _create.createType)('AccountIndex', (0, _util.u8aToBn)(decoded, true));
  }

  static decodeU8a(value) {
    // This allows us to instantiate an address with a raw publicKey. Do this first before
    // we checking the first byte, otherwise we may split an already-existent valid address
    if (value.length === 32) {
      return (0, _create.createType)('AccountId', value);
    } else if (value[0] === 0xff) {
      return (0, _create.createType)('AccountId', value.subarray(1));
    }

    const [offset, length] = _AccountIndex.default.readLength(value);

    return (0, _create.createType)('AccountIndex', (0, _util.u8aToBn)(value.subarray(offset, offset + length), true));
  }
  /**
   * @description The length of the value when encoded as a Uint8Array
   */


  get encodedLength() {
    const rawLength = this.rawLength;
    return rawLength + ( // for 1 byte AccountIndexes, we are not adding a specific prefix
    rawLength > 1 ? 1 : 0);
  }
  /**
   * @description The length of the raw value, either AccountIndex or AccountId
   */


  get rawLength() {
    return this.raw instanceof _AccountIndex.default ? _AccountIndex.default.calcLength(this.raw) : this.raw.encodedLength;
  }
  /**
   * @description Returns a hex string representation of the value
   */


  toHex() {
    return (0, _util.u8aToHex)(this.toU8a());
  }
  /**
   * @description Returns the base runtime type name for this instance
   */


  toRawType() {
    return 'Address';
  }
  /**
   * @description Encodes the value as a Uint8Array as per the SCALE specifications
   * @param isBare true when the value has none of the type-specific prefixes (internal)
   */


  toU8a(isBare) {
    const encoded = this.raw.toU8a().subarray(0, this.rawLength);
    return isBare ? encoded : (0, _util.u8aConcat)(this.raw instanceof _AccountIndex.default ? _AccountIndex.default.writeLength(encoded) : ACCOUNT_ID_PREFIX, encoded);
  }

}

exports.default = Address;