#include "Gwater.h"

CELL def_basin(int row, int col, CELL basin_num, double stream_length,
               CELL old_elev)
{
    int r, rr, c, cc, ct, new_r[9], new_c[9];
    CELL downdir, direction, asp_value, value, new_elev;
    int oldupdir, riteflag, leftflag, thisdir;

    for (;;) {
        bas[SEG_INDEX(bas_seg, row, col)] = basin_num;
        FLAG_SET(swale, row, col);
        ct = 0;
        for (r = row - 1, rr = 0; rr < 3; r++, rr++) {
            for (c = col - 1, cc = 0; cc < 3; c++, cc++) {
                if (r >= 0 && c >= 0 && r < nrows && c < ncols) {
                    if (r == row && c == col)
                        continue;
                    value = asp[SEG_INDEX(asp_seg, r, c)];
                    if (value < 0)
                        value = -value;
                    if (value == drain[rr][cc]) {
                        value = FLAG_GET(swale, r, c);
                        if (value) {
                            new_r[++ct] = r;
                            new_c[ct] = c;
                        }
                    }
                }
            }
        }
        if (ct == 0) {
            no_stream(row, col, basin_num, stream_length, old_elev);
            return (basin_num);
        }
        if (ct >= 2) {
            basin_num = split_stream(row, col, new_r, new_c, ct, basin_num,
                                     stream_length, old_elev);
            return (basin_num);
        }
        oldupdir = drain[row - new_r[1] + 1][col - new_c[1] + 1];
        downdir = asp[SEG_INDEX(asp_seg, row, col)];
        if (downdir < 0)
            downdir = -downdir;
        riteflag = leftflag = 0;
        for (r = row - 1, rr = 0; rr < 3; r++, rr++) {
            for (c = col - 1, cc = 0; cc < 3; c++, cc++) {
                if (r >= 0 && c >= 0 && r < nrows && c < ncols) {
                    if (r == row && c == col)
                        continue;
                    direction = asp[SEG_INDEX(asp_seg, r, c)];
                    if (direction == drain[rr][cc]) {
                        thisdir = updrain[rr][cc];
                        switch (haf_basin_side(oldupdir, downdir, thisdir)) {
                        case LEFT:
                            overland_cells(r, c, basin_num, basin_num - 1,
                                           &new_elev);
                            leftflag++;
                            break;
                        case RITE:
                            overland_cells(r, c, basin_num, basin_num,
                                           &new_elev);
                            riteflag++;
                            break;
                        }
                    }
                }
            }
        }
        if (leftflag > riteflag)
            haf[SEG_INDEX(haf_seg, row, col)] = basin_num - 1;
        else
            haf[SEG_INDEX(haf_seg, row, col)] = basin_num;
        if (sides == 8) {
            if (new_r[1] != row && new_c[1] != col)
                stream_length += diag;
            else if (new_r[1] != row)
                stream_length += window.ns_res;
            else
                stream_length += window.ew_res;
        }
        else { /* sides == 4 */

            asp_value = asp[SEG_INDEX(asp_seg, row, col)];
            if (asp_value < 0)
                asp_value = -asp_value;

            if (asp_value == 2 || asp_value == 6) {
                if (new_r[1] != row)
                    stream_length += window.ns_res;
                else
                    stream_length += diag;
            }
            else { /* asp_value == 4, 8 */

                if (new_c[1] != col)
                    stream_length += window.ew_res;
                else
                    stream_length += diag;
            }
        }
        row = new_r[1];
        col = new_c[1];
    }
}
