/*
  A require.s2 module which adds some functionality
  to the various Fossil classes.

  This module is not intended to be used more than once and should not
  be cached. Thus, to use it:

  Fossil.require(['nocache!fsl/extendFossil'],proc(){})
*/


assert Fossil;
assert Fossil.Context;
Fossil.artifactTypes && return Fossil /* already ran this module */;


//Fossil.loadModule = s2.loadModule2;
//Fossil.importScript = s2.import2;

/**
  Counterpart of the C-level fsl_aatype_e enum.
*/
Fossil.artifactTypes = enum {
    ANY: 0,
    CHECKIN: 1,
    CLUSTER: 2,
    CONTROL: 3,
    WIKI: 4,
    TICKET: 5,
    ATTACHMENT: 6,
    EVENT: 7,
    FORUMPOST: 8
};

/**
    Fetches the first row from the given SQL statement (String or
    Buffer) and returns it as an Object (if asArray is false) or an
    Array (if asArray is true).

    If the bind argument is passed in then it is passed on to the
    Stmt.bind() method of the underlying statement. Use an array to
    bind multiple values. To specify the third parameter when there is
    nothing to bind, pass the undefined value as the second argument.
    i.e. bind===undefined is treated as "nothing to bind," instead of
    binding undefined/null.

    Throws on error. Returns undefined if no row is found.
*/
Fossil.Db.selectRow = proc(sql, bind = undefined, asArray = false){
    affirm this inherits Fossil.Db;
    const st = this.prepare(sql);
    var rc;
    const ex = catch {
        st.bind(bind);
        rc = asArray ? st.stepArray() : st.stepObject();
    };
    st.finalize();
    ex ? throw ex : return rc;
};

/**
   Returns an array containing the complete results of each row in the
   given SQL's result set. If asArray is true, each row is returned as
   an array of column values in the same order as the result set's,
   else each is returned an an Object of column name/value pairs with
   columns in an an unspecified order.

   The bind parameter may hold value(s) to bind to the given SQL.
*/
Fossil.Db.selectAll = proc(sql, bind = undefined, asArray = true){
    affirm this inherits Fossil.Db;
    const rc = [];
    this.each({
        sql: sql,
        bind: bind,
        mode: asArray ? 1 : 0,
        callback: rc
    });
    return rc;
};

/**
    Given a SELECT-style query and optional bind parameters
    (either a single value for a single param or an array
    of multiple params), this routine simply dumps out
    the results of the query. bind===undefined is treated
    as "nothing to bind," instead of binding undefined/null.
*/
Fossil.Db.dumpQuery = proc(sql,bind = undefined, separator='\t'){
    affirm this inherits Fossil.Db;
    return this.each({
        sql:sql,
        bind:bind, // note that undefined value is treated as non-existent here
        callback:proc(){
            (1===rowNumber) && print(columnNames.join(separator));
            print(this.join(separator));
        }
    });
};

/**
    Changes to the given dir and pushes the (old) current dir
    to the directory stack. To change back to the pre-pushd()
    directory, call Fossil.file.popd(). This function relies
    on this 'this' object beeing Fossil.file. Throws if it
    cannot change directories.

    The array of pushed directory names is available after calling
    this function one time via the property
    Fossil.file.pushd.dirStack. The most recent directory is at the
    end of that array. If that property is undefined, pushd() has
    never been called (or someone removed the property). If it is an
    empty array, there are currently no directories in the stack.
*/
Fossil.file.pushd = proc callee(dir){
    affirm 'string' === typename dir;
    const curdir = this.currentDir();
    this.chdir(dir);
    (callee.dirStack ||| (callee.dirStack = [])).push( curdir );
};

/**
    Pops the directory mostly recently pushed by Fossil.file.pushd()
    off of the directory stack and changes to that directory. Throws
    if called when no directories can be popped.
*/
Fossil.file.popd = proc(){
    const list = this.pushd.dirStack;
    const len = (list ? list.length() : 0)
        ||| throw "Directory stack is empty.";
    this.chdir(list[len-1]);
    return list.pop()
};

return Fossil;
