import { isObject } from '../codec';
import { PERMISSION } from '../constant';
export class BaseCommand {
    constructor(argMap) {
        this._schema = {};
        this._argMap = {};
        this._argMap = argMap;
        if (!this._argMap.options) {
            this._argMap.options = {};
        }
    }
    get permission() {
        switch (this._permission) {
            case PERMISSION.CREATE:
            case PERMISSION.UPDATE:
            case PERMISSION.DELETE:
                return PERMISSION.WRITE;
            default:
                return this._permission;
        }
    }
    get argMap() {
        return this._argMap;
    }
    get schema() {
        return this._schema;
    }
    augmentOptions(options) {
        this.argMap.options = Object.assign({}, this.argMap.options, options);
    }
    inspect() {
        const args = clean(JSON.parse(JSON.stringify(this.argMap)));
        function clean(d) {
            for (const k of Object.keys(d)) {
                if (isObject(d[k])) {
                    if (Object.keys(d[k]).length === 0) {
                        if (JSON.stringify(d[k]) !== '{}') {
                            delete d[k];
                        }
                    }
                    else {
                        clean(d[k]);
                    }
                }
                if (d[k] === undefined) {
                    delete d[k];
                }
            }
            return d;
        }
        return Object.assign(Object.assign({}, args), { command: this.name });
    }
}
export class AggregateCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'aggregate';
        this._schema = {
            pipeline: 'array',
            options: {
                type: 'object',
                required: false,
                rule: {
                    explain: {
                        type: 'boolean',
                        required: false,
                    },
                    allowDiskUse: {
                        type: 'boolean',
                        required: false,
                    },
                    maxTimeMS: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    bypassDocumentValidation: {
                        type: 'boolean',
                        required: false,
                    },
                    raw: {
                        type: 'boolean',
                        required: false,
                    },
                    promoteLongs: {
                        type: 'boolean',
                        required: false,
                    },
                    promoteValues: {
                        type: 'boolean',
                        required: false,
                    },
                    promoteBuffers: {
                        type: 'boolean',
                        required: false,
                    },
                    collation: {
                        type: 'object',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.AGGREGATE;
    }
}
export class CountCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'count';
        this._schema = {
            query: 'object',
            options: {
                type: 'object',
                required: false,
                rule: {
                    limit: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    skip: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    maxTimeMS: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                },
            },
        };
        this._permission = PERMISSION.READ;
    }
}
export class DistinctCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'distinct';
        this._schema = {
            key: 'string',
            query: 'object',
            options: {
                type: 'object',
                required: false,
            },
        };
        this._permission = PERMISSION.READ;
    }
}
export class FindDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'findOne';
        this._schema = {
            query: {
                type: 'object',
                required: false,
            },
            options: {
                type: 'object',
                required: false,
                rule: {
                    limit: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    skip: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    maxTimeMS: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    sort: {
                        type: 'sort',
                        required: false,
                    },
                    projection: {
                        type: 'projection',
                        required: false,
                    },
                    hint: {
                        type: 'object',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.READ;
    }
}
export class FindDocumentsCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'find';
        this._schema = {
            query: {
                type: 'object',
                required: false,
            },
            options: {
                type: 'object',
                required: false,
                rule: {
                    limit: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    skip: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    maxTimeMS: {
                        type: 'int',
                        required: false,
                        min: 0,
                    },
                    sort: {
                        type: 'sort',
                        required: false,
                    },
                    projection: {
                        type: 'projection',
                        required: false,
                    },
                    hint: {
                        type: 'object',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.READ;
    }
}
export class InsertDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'insertOne';
        this._schema = {
            doc: 'field',
            options: {
                type: 'object',
                required: false,
            },
        };
        this._permission = PERMISSION.CREATE;
    }
}
export class InsertDocumentsCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'insertMany';
        this._schema = {
            docs: 'fields',
            options: {
                type: 'object',
                required: false,
            },
        };
        this._permission = PERMISSION.CREATE;
    }
}
export class FindAndUpdateDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'findOneAndUpdate';
        this._schema = {
            filter: 'object',
            update: 'object',
            options: {
                type: 'object',
                required: false,
                rule: {
                    maxTimeMS: {
                        type: 'int',
                        min: 0,
                        required: false,
                    },
                    sort: {
                        type: 'sort',
                        required: false,
                    },
                    upsert: {
                        type: 'boolean',
                        required: false,
                    },
                    projection: {
                        type: 'projection',
                        required: false,
                    },
                    returnNewDocument: {
                        type: 'boolean',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.UPDATE;
    }
}
export class UpdateDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'updateOne';
        this._schema = {
            filter: 'object',
            update: 'nobject',
            options: {
                type: 'object',
                required: false,
                rule: {
                    upsert: {
                        type: 'boolean',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.UPDATE;
    }
}
export class UpdateDocumentsCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'updateMany';
        this._schema = {
            filter: 'object',
            update: 'nobject',
            options: {
                type: 'object',
                required: false,
                rule: {
                    upsert: {
                        type: 'boolean',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.UPDATE;
    }
}
export class FindAndReplaceDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'findOneAndReplace';
        this._schema = {
            filter: 'object',
            replacement: 'object',
            options: {
                type: 'object',
                required: false,
                rule: {
                    maxTimeMS: {
                        type: 'int',
                        min: 0,
                        required: false,
                    },
                    sort: {
                        type: 'sort',
                        required: false,
                    },
                    upsert: {
                        type: 'boolean',
                        required: false,
                    },
                    projection: {
                        type: 'projection',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.UPDATE;
    }
}
export class ReplaceDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'replaceOne';
        this._schema = {
            filter: 'object',
            doc: 'object',
            options: {
                type: 'object',
                required: false,
                rule: {
                    upsert: {
                        type: 'boolean',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.UPDATE;
    }
}
export class FindAndDeleteDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'findOneAndDelete';
        this._schema = {
            filter: 'object',
            options: {
                type: 'object',
                required: false,
                rule: {
                    maxTimeMS: {
                        type: 'int',
                        min: 0,
                        required: false,
                    },
                    sort: {
                        type: 'sort',
                        required: false,
                    },
                    projection: {
                        type: 'object',
                        required: false,
                    },
                },
            },
        };
        this._permission = PERMISSION.DELETE;
    }
}
export class DeleteDocumentCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'deleteOne';
        this._schema = {
            filter: {
                type: 'object',
            },
            options: {
                type: 'object',
                required: false,
            },
        };
        this._permission = PERMISSION.DELETE;
    }
}
export class DeleteDocumentsCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'deleteMany';
        this._schema = {
            filter: {
                type: 'object',
            },
            options: {
                type: 'object',
                required: false,
            },
        };
        this._permission = PERMISSION.DELETE;
    }
}
export class StartTransactionCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'startTransaction';
    }
}
export class CommitTransactionCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'commitTransaction';
    }
}
export class AbortTransactionCommand extends BaseCommand {
    constructor() {
        super(...arguments);
        this.name = 'abortTransaction';
    }
}
//# sourceMappingURL=data:application/json;base64, 