"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.partition = exports.filterMap_ = exports.filterMap = exports.filter_ = exports.filter = exports.separate = exports.compact = exports.some_ = exports.some = exports.every_ = exports.every = exports.filterWithIndex_ = exports.filterWithIndex = exports.filterMapWithIndex_ = exports.filterMapWithIndex = exports.partitionWithIndex_ = exports.partitionWithIndex = exports.partitionMapWithIndex_ = exports.partitionMapWithIndex = exports.singleton = exports.reduceRightWithIndex_ = exports.reduceRightWithIndex = exports.reduceWithIndex_ = exports.reduceWithIndex = exports.map_ = exports.map = exports.mapWithIndex_ = exports.mapWithIndex = exports.empty = exports.lookup = exports.lookup_ = exports.pop_ = exports.pop = exports.modifyAt_ = exports.modifyAt = exports.updateAt_ = exports.updateAt = exports.deleteAt_ = exports.deleteAt = exports.hasOwnProperty = exports.insertAt_ = exports.insertAt = exports.collect_ = exports.collect = exports.values = exports.keys = exports.isEmpty = exports.size = exports.toMutable = exports.fromMutable = void 0;
exports.fromArray = exports.toArray = exports.reduceRight_ = exports.reduceRight = exports.reduce_ = exports.reduce = exports.partitionMap_ = exports.partitionMap = exports.partition_ = void 0;
// ets_tracing: off
require("../../../Operator");
const O = __importStar(require("../../../Option"));
const A = __importStar(require("../Array"));
const Tp = __importStar(require("../Tuple"));
/**
 * Build a readonly record from a mutable version
 */
function fromMutable(r) {
    return Object.assign({}, r);
}
exports.fromMutable = fromMutable;
/**
 * Converts the record to a mutable version
 */
function toMutable(r) {
    return Object.assign({}, r);
}
exports.toMutable = toMutable;
/**
 * Calculate the number of key/value pairs in a record
 */
function size(r) {
    return Object.keys(r).length;
}
exports.size = size;
/**
 * Test whether a record is empty
 */
function isEmpty(r) {
    return Object.keys(r).length === 0;
}
exports.isEmpty = isEmpty;
/**
 * Extract record keys
 */
function keys(r) {
    return Object.keys(r).sort();
}
exports.keys = keys;
/**
 * Extract record values
 */
function values(r) {
    return Object.keys(r)
        .sort()
        .map((s) => r[s]);
}
exports.values = values;
/**
 * Map a record into an array
 */
function collect(f) {
    return (r) => collect_(r, f);
}
exports.collect = collect;
/**
 * Map a record into an array
 */
function collect_(r, f) {
    const out = [];
    for (const key of keys(r)) {
        out.push(f(key, r[key]));
    }
    return out;
}
exports.collect_ = collect_;
/**
 * Insert or replace a key/value pair in a record
 */
function insertAt(k, a) {
    return (r) => insertAt_(r, k, a);
}
exports.insertAt = insertAt;
/**
 * Insert or replace a key/value pair in a record
 */
function insertAt_(r, k, a) {
    if (r[k] === a) {
        return r;
    }
    const out = Object.assign({}, r);
    out[k] = a;
    return out;
}
exports.insertAt_ = insertAt_;
/**
 * Check if k is a key
 */
function hasOwnProperty(r, k) {
    return Object.prototype.hasOwnProperty.call(r, k);
}
exports.hasOwnProperty = hasOwnProperty;
/**
 * Delete a key
 */
function deleteAt(k) {
    return (r) => deleteAt_(r, k);
}
exports.deleteAt = deleteAt;
/**
 * Delete a key
 */
function deleteAt_(r, k) {
    if (!Object.prototype.hasOwnProperty.call(r, k)) {
        return r;
    }
    const out = Object.assign({}, r);
    delete out[k];
    return out;
}
exports.deleteAt_ = deleteAt_;
/**
 * Update a key value pair
 */
function updateAt(k, a) {
    return (r) => updateAt_(r, k, a);
}
exports.updateAt = updateAt;
/**
 * Update a key value pair
 */
function updateAt_(r, k, a) {
    if (!hasOwnProperty(r, k)) {
        return O.none;
    }
    if (r[k] === a) {
        return O.some(r);
    }
    const out = Object.assign({}, r);
    out[k] = a;
    return O.some(out);
}
exports.updateAt_ = updateAt_;
/**
 * Modify the value at key k with f
 */
function modifyAt(k, f) {
    return (r) => modifyAt_(r, k, f);
}
exports.modifyAt = modifyAt;
/**
 * Modify the value at key k with f
 */
function modifyAt_(r, k, f) {
    if (!hasOwnProperty(r, k)) {
        return O.none;
    }
    const out = Object.assign({}, r);
    out[k] = f(r[k]);
    return O.some(out);
}
exports.modifyAt_ = modifyAt_;
/**
 * Delete a key and value from a map, returning the value as well as the subsequent map
 */
function pop(k) {
    return (r) => pop_(r, k);
}
exports.pop = pop;
/**
 * Delete a key and value from a map, returning the value as well as the subsequent map
 */
function pop_(r, k) {
    const deleteAtk = deleteAt(k);
    const oa = lookup_(r, k);
    return O.isNone(oa) ? O.none : O.some(Tp.tuple(oa.value, deleteAtk(r)));
}
exports.pop_ = pop_;
/**
 * Lookup the value for a key in a record
 */
function lookup_(r, k) {
    return Object.prototype.hasOwnProperty.call(r, k) ? O.some(r[k]) : O.none;
}
exports.lookup_ = lookup_;
/**
 * Lookup the value for a key in a record
 */
function lookup(k) {
    return (r) => (Object.prototype.hasOwnProperty.call(r, k) ? O.some(r[k]) : O.none);
}
exports.lookup = lookup;
/**
 * Empty record
 */
exports.empty = {};
/**
 * Map a record passing the keys to the iterating function
 */
function mapWithIndex(f) {
    return (fa) => mapWithIndex_(fa, f);
}
exports.mapWithIndex = mapWithIndex;
/**
 * Map a record passing the keys to the iterating function
 */
function mapWithIndex_(fa, f) {
    const out = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        out[key] = f(key, fa[key]);
    }
    return out;
}
exports.mapWithIndex_ = mapWithIndex_;
/**
 * Map a record passing the values to the iterating function
 */
function map(f) {
    return (fa) => map_(fa, f);
}
exports.map = map;
/**
 * Map a record passing the values to the iterating function
 */
function map_(fa, f) {
    return mapWithIndex_(fa, (_, a) => f(a));
}
exports.map_ = map_;
/**
 * Reduce the record passing the index toghether with the value to f
 */
function reduceWithIndex(b, f) {
    return (fa) => reduceWithIndex_(fa, b, f);
}
exports.reduceWithIndex = reduceWithIndex;
/**
 * Reduce the record passing the index toghether with the value to f
 */
function reduceWithIndex_(fa, b, f) {
    let out = b;
    const keys = Object.keys(fa).sort();
    const len = keys.length;
    for (let i = 0; i < len; i++) {
        const k = keys[i];
        out = f(k, out, fa[k]);
    }
    return out;
}
exports.reduceWithIndex_ = reduceWithIndex_;
/**
 * Reduce the record passing the index toghether with the value to f
 *
 * Inverted order
 */
function reduceRightWithIndex(b, f) {
    return (fa) => reduceRightWithIndex_(fa, b, f);
}
exports.reduceRightWithIndex = reduceRightWithIndex;
/**
 * Reduce the record passing the index toghether with the value to f
 *
 * Inverted order
 */
function reduceRightWithIndex_(fa, b, f) {
    let out = b;
    const keys = Object.keys(fa).sort();
    const len = keys.length;
    for (let i = len - 1; i >= 0; i--) {
        const k = keys[i];
        out = f(k, fa[k], out);
    }
    return out;
}
exports.reduceRightWithIndex_ = reduceRightWithIndex_;
/**
 * Create a record with one key/value pair
 */
function singleton(k, a) {
    return { [k]: a };
}
exports.singleton = singleton;
/**
 * Partition a record using f that also consumes the entry key
 */
function partitionMapWithIndex(f) {
    return (fa) => partitionMapWithIndex_(fa, f);
}
exports.partitionMapWithIndex = partitionMapWithIndex;
/**
 * Partition a record using f that also consumes the entry key
 */
function partitionMapWithIndex_(fa, f) {
    const left = {};
    const right = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        const e = f(key, fa[key]);
        switch (e._tag) {
            case "Left":
                left[key] = e.left;
                break;
            case "Right":
                right[key] = e.right;
                break;
        }
    }
    return {
        left,
        right
    };
}
exports.partitionMapWithIndex_ = partitionMapWithIndex_;
function partitionWithIndex(predicateWithIndex) {
    return (fa) => partitionWithIndex_(fa, predicateWithIndex);
}
exports.partitionWithIndex = partitionWithIndex;
function partitionWithIndex_(fa, predicateWithIndex) {
    const left = {};
    const right = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        const a = fa[key];
        if (predicateWithIndex(key, a)) {
            right[key] = a;
        }
        else {
            left[key] = a;
        }
    }
    return {
        left,
        right
    };
}
exports.partitionWithIndex_ = partitionWithIndex_;
function filterMapWithIndex(f) {
    return (fa) => filterMapWithIndex_(fa, f);
}
exports.filterMapWithIndex = filterMapWithIndex;
/**
 * Filter & map the record entries with f that consumes also the entry index
 */
function filterMapWithIndex_(fa, f) {
    const r = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        const optionB = f(key, fa[key]);
        if (O.isSome(optionB)) {
            r[key] = optionB.value;
        }
    }
    return r;
}
exports.filterMapWithIndex_ = filterMapWithIndex_;
function filterWithIndex(predicateWithIndex) {
    return (fa) => filterWithIndex_(fa, predicateWithIndex);
}
exports.filterWithIndex = filterWithIndex;
function filterWithIndex_(fa, predicateWithIndex) {
    const out = {};
    let changed = false;
    for (const key in fa) {
        if (Object.prototype.hasOwnProperty.call(fa, key)) {
            const a = fa[key];
            if (predicateWithIndex(key, a)) {
                out[key] = a;
            }
            else {
                changed = true;
            }
        }
    }
    return changed ? out : fa;
}
exports.filterWithIndex_ = filterWithIndex_;
/**
 * Checks a predicate against all the record entries
 */
function every(predicate) {
    return (r) => every_(r, predicate);
}
exports.every = every;
/**
 * Checks a predicate against all the record entries
 */
function every_(r, predicate) {
    for (const k in r) {
        if (!predicate(r[k])) {
            return false;
        }
    }
    return true;
}
exports.every_ = every_;
/**
 * Checks a predicate against some of the record entries
 */
function some(predicate) {
    return (r) => some_(r, predicate);
}
exports.some = some;
/**
 * Checks a predicate against some of the record entries
 */
function some_(r, predicate) {
    for (const k in r) {
        if (predicate(r[k])) {
            return true;
        }
    }
    return false;
}
exports.some_ = some_;
/**
 * Drop the None entries
 */
const compact = (fa) => {
    const r = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        const optionA = fa[key];
        if (O.isSome(optionA)) {
            r[key] = optionA.value;
        }
    }
    return r;
};
exports.compact = compact;
/**
 * Separate the record entries
 */
const separate = (fa) => {
    const left = {};
    const right = {};
    const keys = Object.keys(fa);
    for (const key of keys) {
        const e = fa[key];
        switch (e._tag) {
            case "Left":
                left[key] = e.left;
                break;
            case "Right":
                right[key] = e.right;
                break;
        }
    }
    return {
        left,
        right
    };
};
exports.separate = separate;
/**
 * Filter record entries according to a predicate
 */
const filter = (predicate) => (fa) => (0, exports.filter_)(fa, predicate);
exports.filter = filter;
/**
 * Filter record entries according to a predicate
 */
const filter_ = (fa, predicate) => filterWithIndex_(fa, (_, a) => predicate(a));
exports.filter_ = filter_;
/**
 * Filter & map record entries according to a predicate
 */
const filterMap = (f) => (fa) => (0, exports.filterMap_)(fa, f);
exports.filterMap = filterMap;
/**
 * Filter & map record entries according to a predicate
 */
const filterMap_ = (fa, f) => filterMapWithIndex_(fa, (_, a) => f(a));
exports.filterMap_ = filterMap_;
/**
 * Partition record entries according to a predicate
 */
const partition = (predicate) => (fa) => (0, exports.partition_)(fa, predicate);
exports.partition = partition;
/**
 * Partition record entries according to a predicate
 */
const partition_ = (fa, predicate) => partitionWithIndex_(fa, (_, a) => predicate(a));
exports.partition_ = partition_;
/**
 * Partition & map record entries
 */
const partitionMap = (f) => (fa) => (0, exports.partitionMap_)(fa, f);
exports.partitionMap = partitionMap;
/**
 * Partition & map record entries
 */
const partitionMap_ = (fa, f) => partitionMapWithIndex_(fa, (_, a) => f(a));
exports.partitionMap_ = partitionMap_;
/**
 * Reduce record entries
 */
const reduce = (b, f) => (fa) => (0, exports.reduce_)(fa, b, f);
exports.reduce = reduce;
/**
 * Reduce record entries
 */
const reduce_ = (fa, b, f) => reduceWithIndex_(fa, b, (_, b, a) => f(b, a));
exports.reduce_ = reduce_;
/**
 * Reduce record entries in inverted order
 */
const reduceRight = (b, f) => (fa) => (0, exports.reduceRight_)(fa, b, f);
exports.reduceRight = reduceRight;
/**
 * Reduce record entries in inverted order
 */
const reduceRight_ = (fa, b, f) => reduceRightWithIndex_(fa, b, (_, a, b) => f(a, b));
exports.reduceRight_ = reduceRight_;
/**
 * Converts a record into an array of [key, value]
 */
exports.toArray = collect(Tp.tuple);
/**
 * Converts an array of [key, value] into a record
 */
const fromArray = (_) => A.reduce_(_, {}, (b, { tuple: [k, v] }) => Object.assign(b, { [k]: v }));
exports.fromArray = fromArray;
//# sourceMappingURL=index.js.map