"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMemberExpression = exports.combine = void 0;
const ast_1 = require("../ast");
const toCodeString_1 = __importDefault(require("../toCodeString"));
const combineExpressions_1 = __importDefault(require("./combineExpressions"));
const simplify_1 = __importDefault(require("./simplify"));
const splitExpressions_1 = __importDefault(require("./splitExpressions"));
const traverse_1 = require("@glas/traverse");
function combine(left, operator, right) {
    if (left == null) {
        return right;
    }
    if (right == null) {
        return left;
    }
    return new ast_1.BinaryExpression({ left, operator, right });
}
exports.combine = combine;
function findAndReplaceMembers(e, member) {
    let count = 0;
    let result = traverse_1.traverse(e, {
        leave(node) {
            if (ast_1.MemberExpression.is(node.left) && ast_1.DotExpression.is(node.left.object)) {
                let dotProperty = node.left.property;
                if (toCodeString_1.default(dotProperty) === toCodeString_1.default(member)) {
                    count++;
                    // return the same expression, but remove the member expression so
                    //  .foo is Bar => . is Bar
                    return node.patch({ left: node.left.object });
                }
            }
        }
    });
    return count > 0 ? result : null;
}
function getMemberExpression(e, member) {
    // must combine all member expression values
    let terms = [...splitExpressions_1.default(e)].map(e => {
        return findAndReplaceMembers(e, member);
    }).filter(e => e != null);
    return combineExpressions_1.default(terms);
}
exports.getMemberExpression = getMemberExpression;
function getMemberTypeExpression(t, member) {
    let e = t.value;
    let value = getMemberExpression(e, member);
    if (value == null) {
        return null;
    }
    value = ast_1.Reference.is(value) ? value : new ast_1.TypeExpression({ value });
    return simplify_1.default(value);
}
exports.default = getMemberTypeExpression;
