#if !defined(FSL_DIBU_NCU_INCLUDED)
#define FSL_DIBU_NCU_INCLUDED
#include <ncurses.h>
#include "libfossil.h"


/**
   Column indexes for fsl_dibu_ncu::maxWidths and friends.
*/
enum FslDiffBuilderCols {
FDBCols_NUM1 = 0, FDBCols_TEXT1,
FDBCols_MOD,
FDBCols_NUM2, FDBCols_TEXT2,
FDBCols_count
};

/**
   Internal state for the ncurses unified-format-ish diff
   builder.
*/
struct fsl_dibu_ncu {
  /**
     Largest column width we've yet seen.

     FIXME: these are in bytes, not text columns. The current code may
     truncate multibyte characters.
  */
  uint32_t maxWidths[FDBCols_count];
  /**
     Max line numbers seen for the LHS/RHS input files. This is likely
     higher than the number of diff lines.

     This can be used, e.g., to size and allocate a curses PAD in the
     second pass of the start() method.
  */
  uint32_t lineCount[2];
  /**
     The actual number of lines needed for rendering the file.
  */
  uint32_t displayLines;
  /**
     The column width, in bytes, needed for rendering the file. May
     currently misbehave with multi-byte characters.
  */
  uint32_t displayWidth;
  /**
     Rendering surface for the builder. Owned by this object.
   */
  WINDOW * pad;
  /**
     Internal rendering position tracker.
  */
  struct {
    int y;
    int x;
  } cursor;
  /**
     Internal buffer.
  */
  fsl_buffer buf;
};
typedef struct fsl_dibu_ncu fsl_dibu_ncu;


/**
   Factory function for the "ncu" (ncurses unified) diff
   builder.

   The new instance's pimpl member is a (fsl_diff_builde_ncu*).

   It must not be used via the diff APIs until after ncurses screen
   mode has been activated via `initscr()`. Violations are met with
   undefined behaviour. Similarly, ncurses apparently cannot render
   non-ASCII UTF8 characters unless the application does something like
   the following before calling `initscr()`:

   ```
   setlocale(LC_ALL, "");
   ```

*/
fsl_dibu * fsl_dibu_ncu_alloc(void);

/**
   Returns true if its argument was allocated via fsl_dibu_ncu_alloc(),
   else false.
 */
bool fsl_dibu_is_ncu(fsl_dibu const * const b);

/**
   If fsl_dibu_is_ncu() returns true for the given build, this
   returns that builder's type-specific state, else it returns NULL.
*/
fsl_dibu_ncu * fsl_dibu_ncu_pimpl(fsl_dibu * const b);

/**
   This is a very basic implementation of a diff viewer intended to be
   run after a fsl_dibu has processed its diffs and is ready
   to be rendered. This enters an input look which accepts navigation
   keys until the user taps 'q' to quit the loop. w must be the target
   window on top of which to render (e.g. stdscr).
*/
void fsl_dibu_ncu_basic_loop(fsl_dibu_ncu * const nc,
                             WINDOW * const w);

/**
   Renders a vertical scrollbar on window tgt at column x, running
   from the given top row to the row (top+barHeight). The scroll
   indicator is rendered depending on the final two arguments:
   lineCount specifies the number of lines in the scrollable
   input and currentLine specifies the top-most line number of the
   currently-displayed data. e.g. a lineCount of 100 and currentLine
   of 1 puts the indicator 1% of the way down the scrollbar. Likewise,
   a lineCount of 100 and currentLine of 90 puts the indicator at the
   90% point.
 */
void fsl_nc_scrollbar_v( WINDOW * const tgt, int top, int x, 
                         int barHeight, int lineCount,
                         int currentLine );


/**
   Works like fsl_nc_scrollbar_v() but renders a horizontal scrollbar
   at the given left/top coordinates of tgt.
*/
void fsl_nc_scrollbar_h( WINDOW * const tgt, int top, int left, 
                         int barWidth, int colCount,
                         int currentCol );

#endif /* FSL_DIBU_NCU_INCLUDED */


