#include "watershed.h"

int accum_down(OUTPUT *output)
{
    double new_length;
    int m, b, num_basins, down_basin;
    B_FACTS *basin_facts, *basin_info, *down_basin_info;
    CAT *down_cat, *cat;
    MAP *map;

    num_basins = output->num_basins;
    basin_facts = output->basin_facts;
    for (b = num_basins - 1; b >= 0; b--) {
        basin_facts[b].accum_length = basin_facts[b].str_length;
        basin_facts[b].accum_slope = basin_facts[b].str_slope;
    }
    for (b = num_basins - 1; b >= 0; b--) {
        basin_info = &(basin_facts[b]);
        down_basin = basin_info->down_basin;
        if (down_basin >= 0) {
            down_basin_info = &(basin_facts[down_basin]);
            down_basin_info->num_cells += basin_info->num_cells;
            new_length = basin_info->accum_length + down_basin_info->str_length;
            if (new_length > down_basin_info->accum_length) {
                down_basin_info->accum_length = new_length;
                down_basin_info->accum_slope =
                    (down_basin_info->str_slope * down_basin_info->str_length +
                     basin_info->accum_slope * basin_info->accum_length) /
                    new_length;
            }
            /* accum map layer information */
            for (m = 0; m < output->num_maps; m++) {
                map = &(output->maps[m]);
                map->basins[down_basin].sum_values += map->basins[b].sum_values;
                if (output->maps[m].do_cats != 0) {
                    cat = &(map->basins[b].first_cat);
                    down_cat = &(map->basins[down_basin].first_cat);
                    while (cat != NULL) {
                        insert_cat(down_cat, cat->cat_val, cat->num_cat);
                        cat = cat->nxt;
                    }
                }
            }
        }
    }
    for (b = num_basins - 1; b >= 0; b--) {
        basin_facts[b].str_length = basin_facts[b].accum_length;
        basin_facts[b].str_slope = basin_facts[b].accum_slope;
    }

    return 0;
}
