"use strict";
exports.__esModule = true;
require("../../typed-array");
var errors = require("./errors");
var RADIX = 3;
var MAX_TRIT_VALUE = (RADIX - 1) / 2;
var MIN_TRIT_VALUE = -MAX_TRIT_VALUE;
exports.TRYTE_WIDTH = MAX_TRIT_VALUE - MIN_TRIT_VALUE + 1;
// All possible tryte values
exports.TRYTE_ALPHABET = '9ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Trytes to trits look up table
exports.TRYTES_TRITS_LUT = [
    [0, 0, 0],
    [1, 0, 0],
    [-1, 1, 0],
    [0, 1, 0],
    [1, 1, 0],
    [-1, -1, 1],
    [0, -1, 1],
    [1, -1, 1],
    [-1, 0, 1],
    [0, 0, 1],
    [1, 0, 1],
    [-1, 1, 1],
    [0, 1, 1],
    [1, 1, 1],
    [-1, -1, -1],
    [0, -1, -1],
    [1, -1, -1],
    [-1, 0, -1],
    [0, 0, -1],
    [1, 0, -1],
    [-1, 1, -1],
    [0, 1, -1],
    [1, 1, -1],
    [-1, -1, 0],
    [0, -1, 0],
    [1, -1, 0],
    [-1, 0, 0],
];
/**
 * Converts trytes or values to trits
 *
 * @method trits
 *
 * @ignore
 *
 * @memberof module:converter
 *
 * @param {String|Number} input - Tryte string or value to be converted.
 *
 * @return {Int8Array} trits
 */
function trits(input) {
    if (typeof input === 'number' && Number.isInteger(input)) {
        return fromValue(input);
    }
    else if (typeof input === 'string') {
        var result = new Int8Array(input.length * exports.TRYTE_WIDTH);
        for (var i = 0; i < input.length; i++) {
            var index = exports.TRYTE_ALPHABET.indexOf(input.charAt(i));
            if (index === -1) {
                throw new Error(errors.INVALID_TRYTES);
            }
            for (var j = 0; j < exports.TRYTE_WIDTH; j++) {
                result[i * exports.TRYTE_WIDTH + j] = exports.TRYTES_TRITS_LUT[index][j];
            }
        }
        return result;
    }
    else {
        throw new Error(errors.INVALID_TRYTES);
    }
}
exports.trits = trits;
/**
 * This method converts [trytes](https://docs.iota.org/docs/getting-started/0.1/introduction/ternary) to trits.
 *
 * ## Related methods
 *
 * To convert ASCII characters to trytes, use the [`asciiToTrytes()`]{@link #module_converter.asciiToTrytes} method.
 *
 * @method trytesToTrits
 *
 * @summary Converts trytes to trits.
 *
 * @memberof module:converter
 *
 * @param {String|number} input - Trytes
 *
 * @example
 * ```js
 * let trits = Converter.trytesToTrits('IOTA');
 * ```
 *
 * @return {Int8Array} trits
 *
 * @throws {errors.INVALID_TRYTES}: Make sure that the `input` argument contains only valid trytes (A-Z or 9).
 */
exports.trytesToTrits = trits;
/**
 * Converts trits to trytes
 *
 * @method trytes
 *
 * @memberof module:converter
 *
 * @ignore
 *
 * @param {Int8Array} trits
 *
 * @return {String} trytes
 */
// tslint:disable-next-line no-shadowed-variable
function trytes(trits) {
    if (!(trits instanceof Int8Array) && !Array.isArray(trits)) {
        throw new Error(errors.INVALID_TRITS);
    }
    var result = '';
    for (var i = 0; i < trits.length / exports.TRYTE_WIDTH; i++) {
        var j = 0;
        for (var k = 0; k < exports.TRYTE_WIDTH; k++) {
            j += trits[i * exports.TRYTE_WIDTH + k] * Math.pow(exports.TRYTE_WIDTH, k);
        }
        if (j < 0) {
            j += exports.TRYTE_ALPHABET.length;
        }
        result += exports.TRYTE_ALPHABET.charAt(j);
    }
    return result;
}
exports.trytes = trytes;
/**
 * This method converts [trits](https://docs.iota.org/docs/getting-started/0.1/introduction/ternary) to trytes.
 *
 * ## Related methods
 *
 * To convert trytes to ASCII characters, use the [`trytesToAscii()`]{@link #module_converter.trytesToAscii} method.
 *
 * @method tritsToTrytes
 *
 * @summary Converts trits to trytes.
 *
 * @memberof module:converter
 *
 * @param {String|number} input - Trits
 *
 * @example
 * ```js
 * let trytes = Converter.tritsToTrytes(trits);
 * ```
 *
 * @return {Int8Array} trytes
 *
 * @throws {errors.INVALID_TRITS}: Make sure that the `input` argument contains an array of trits.
 */
exports.tritsToTrytes = trytes;
/**
 * Converts trits into an integer value
 *
 * @method value
 *
 * @ignore
 *
 * @memberof module:converter
 *
 * @param {Int8Array} trits
 *
 * @return {Number}
 */
// tslint:disable-next-line no-shadowed-variable
function value(trits) {
    var returnValue = 0;
    for (var i = trits.length; i-- > 0;) {
        returnValue = returnValue * RADIX + trits[i];
    }
    return returnValue;
}
exports.value = value;
/**
 * This method converts [trits](https://docs.iota.org/docs/getting-started/0.1/introduction/ternary) to a number.
 *
 * ## Related methods
 *
 * To convert trytes to trits, use the [`trytesToTrits()`]{@link #module_converter.trytesToTrits} method.
 * To convert trits to trytes, use the [`tritsToTrytes()`]{@link #module_converter.tritsToTrytes} method.
 *
 * @method tritsToValue
 *
 * @summary Converts trits to a number.
 *
 * @memberof module:converter
 *
 * @param {String|number} input - Trits
 *
 * @example
 * ```js
 * let number = Converter.tritsToValue(trits);
 * ```
 *
 * @return {Int8Array} number
 */
exports.tritsToValue = value;
/**
 * Converts an integer value to trits
 *
 * @method fromValue
 *
 * @ignore
 *
 * @memberof module:converter
 *
 * @param {Number} value
 *
 * @return {Int8Array} trits
 */
// tslint:disable-next-line no-shadowed-variable
function fromValue(value) {
    var destination = new Int8Array(value ? 1 + Math.floor(Math.log(2 * Math.max(1, Math.abs(value))) / Math.log(RADIX)) : 0);
    var absoluteValue = value < 0 ? -value : value;
    var i = 0;
    while (absoluteValue > 0) {
        var remainder = absoluteValue % RADIX;
        absoluteValue = Math.floor(absoluteValue / RADIX);
        if (remainder > MAX_TRIT_VALUE) {
            remainder = MIN_TRIT_VALUE;
            absoluteValue++;
        }
        destination[i] = remainder;
        i++;
    }
    if (value < 0) {
        for (var j = 0; j < destination.length; j++) {
            destination[j] = -destination[j];
        }
    }
    return destination;
}
exports.fromValue = fromValue;
/**
 * This method converts a number to [trits](https://docs.iota.org/docs/getting-started/0.1/introduction/ternary).
 *
 * ## Related methods
 *
 * To convert trits to trytes, use the [`tritsToTrytes()`]{@link #module_converter.tritsToTrytes} method.
 *
 * @method valueToTrits
 *
 * @summary Converts trits to a number.
 *
 * @memberof module:converter
 *
 * @param {String|number} input - Number
 *
 * @example
 * ```js
 * let trits = Converter.valueToTrits(9);
 * ```
 *
 * @return {Int8Array} trits
 */
exports.valueToTrits = fromValue;
//# sourceMappingURL=trits.js.map