"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilePathMatcherT = exports.NoStringMatcherT = exports.PrefixMatcherT = exports.KindMatcherT = exports.MakeMatcher = exports.GlobMatcher = exports.ExactMatcher = exports.AlwaysMatcher = void 0;
const tslib_1 = require("tslib");
const match_1 = require("../match");
const parse_path_1 = tslib_1.__importDefault(require("../match/parse-path"));
class AlwaysMatcher {
    constructor() { }
    createName(args) {
        if (args.length !== 1)
            throw new TypeError(`AlwaysMatcher: args should be 1 item.`);
        return args[0];
    }
    createGoalIdFromArgs(args) {
        const arg = this.createName(args);
        return {
            id: this.createName([arg]),
            args: [arg],
            execArgs: [arg]
        };
    }
    matchString(name) {
        return this.createGoalIdFromArgs([name]);
    }
    matchGoalID(id, args) {
        if (args.length !== 1)
            return null;
        return this.createGoalIdFromArgs(args);
    }
}
exports.AlwaysMatcher = AlwaysMatcher;
class ExactMatcher {
    constructor(name) {
        this.name = name;
    }
    createGoalIdFromArgs(args) {
        return { id: this.name, args: [], execArgs: [] };
    }
    matchString(name) {
        if (name === this.name) {
            return this.createGoalIdFromArgs([]);
        }
        else {
            return null;
        }
    }
    matchGoalID(id, args) {
        if (this.name === id && args.length === 0) {
            return this.createGoalIdFromArgs([]);
        }
        else {
            return null;
        }
    }
}
exports.ExactMatcher = ExactMatcher;
class GlobMatcher {
    constructor(pattern) {
        this.pattern = pattern;
        this.matchFunction = (0, match_1.NonPosixifyPatternMatch)(pattern);
    }
    createGoalIdFromArgsImpl(args, pm) {
        const arg = args[0];
        return { id: arg, args, execArgs: pm };
    }
    createGoalIdFromArgs(args) {
        const arg = args[0];
        const pm = this.matchFunction(arg);
        if (!pm)
            throw new Error(`Cannot match ${arg} with ${this.pattern} when creating goal.`);
        return this.createGoalIdFromArgsImpl(args, pm);
    }
    matchString(name) {
        const pm = this.matchFunction(name);
        if (!pm)
            return null;
        else
            return this.createGoalIdFromArgsImpl([name], pm);
    }
    matchGoalID(id, args) {
        if (args.length !== 1)
            return null;
        const arg = args[0];
        const pm = this.matchFunction(arg);
        if (!pm || id !== arg)
            return null;
        return this.createGoalIdFromArgsImpl(args, pm);
    }
}
exports.GlobMatcher = GlobMatcher;
class MakeMatcher {
    constructor(nameMaker) {
        this.nameMaker = nameMaker;
    }
    createGoalIdFromArgs(args) {
        if (args.length !== this.nameMaker.length) {
            throw new TypeError(`MakeMaker args length mismatch`);
        }
        const id = this.nameMaker(...args);
        return { id, args, execArgs: args };
    }
    matchString() {
        return null;
    }
    matchGoalID(id, args) {
        if (args.length !== this.nameMaker.length)
            return null;
        const expected = this.createGoalIdFromArgs(args);
        if (expected.id === id)
            return expected;
        else
            return null;
    }
}
exports.MakeMatcher = MakeMatcher;
class KindMatcherT {
    constructor(prefix, inner) {
        this.prefix = prefix;
        this.inner = inner;
    }
    createGoalIdFromArgs(args) {
        const ex = this.inner.createGoalIdFromArgs(args);
        return this.wrap(ex);
    }
    wrap(ex) {
        return { ...ex, id: this.prefix + ex.id };
    }
    wrapNullable(ex) {
        if (ex)
            return this.wrap(ex);
        else
            return null;
    }
    matchString(name) {
        return this.wrapNullable(this.inner.matchString(name));
    }
    matchGoalID(id, args) {
        if (!id.startsWith(this.prefix))
            return null;
        return this.wrapNullable(this.inner.matchGoalID(id.slice(this.prefix.length), args));
    }
}
exports.KindMatcherT = KindMatcherT;
class PrefixMatcherT {
    constructor(prefix, inner) {
        this.prefix = prefix;
        this.inner = inner;
    }
    createGoalIdFromArgs(args) {
        const ex = this.inner.createGoalIdFromArgs(args);
        return this.wrap(ex);
    }
    wrap(ex) {
        return { ...ex, id: this.prefix + ex.id };
    }
    wrapNullable(ex) {
        if (ex)
            return this.wrap(ex);
        else
            return null;
    }
    matchString(name) {
        if (!name.startsWith(this.prefix))
            return null;
        return this.wrapNullable(this.inner.matchString(name.slice(this.prefix.length)));
    }
    matchGoalID(id, args) {
        if (!id.startsWith(this.prefix))
            return null;
        return this.wrapNullable(this.inner.matchGoalID(id.slice(this.prefix.length), args));
    }
}
exports.PrefixMatcherT = PrefixMatcherT;
class NoStringMatcherT {
    constructor(inner) {
        this.inner = inner;
    }
    createGoalIdFromArgs(args) {
        return this.inner.createGoalIdFromArgs(args);
    }
    matchString(name) {
        return null;
    }
    matchGoalID(id, args) {
        return this.inner.matchGoalID(id, args);
    }
}
exports.NoStringMatcherT = NoStringMatcherT;
class FilePathMatcherT {
    constructor(cfg, inner) {
        this.cfg = cfg;
        this.inner = inner;
    }
    createGoalIdFromArgs(args) {
        const ex = this.inner.createGoalIdFromArgs(args);
        return this.wrap(ex);
    }
    wrap(ex) {
        const pp = new parse_path_1.default(ex.id, ex.execArgs);
        return { ...ex, execArgs: [pp, ...ex.execArgs] };
    }
    wrapNullable(ex) {
        if (ex)
            return this.wrap(ex);
        else
            return null;
    }
    matchString(name) {
        return this.wrapNullable(this.inner.matchString(name));
    }
    matchGoalID(id, args) {
        return this.wrapNullable(this.inner.matchGoalID(id, args));
    }
}
exports.FilePathMatcherT = FilePathMatcherT;
