/* 
 * Copyright (C) 2003 Tim Martin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "game.h"
#include "tiles.h"
#include "map.h"
#include "utilities.h"
#include "utils.h"
#include "connections.h"

extern tiles_t *tiles;
extern map_t *map;
extern game_t *game;

static void 
use_cb(map_t *map, int mapx, int mapy, int owner, 
	     mapobj_t obj, void *rock)
{
    int use;

    /*
     * Power
     */
    use = tiles_getpoweruse(tiles, obj);
    if (use > 0) {
	if (game->power_excess < use) {
	    map_setflag(map, mapx, mapy, MAPFLAG_NOPOWER);
	    game->power_numno++;
	} else {
	    game->power_excess -= use;
	    game->power_numyes++;
	}
    }

    /*
     * Water
     */
    use = tiles_getwateruse(tiles, obj);
    if (use > 0) {
	if (game->water_excess < use) {
	    map_setflag(map, mapx, mapy, MAPFLAG_NOWATER);
	    game->water_numno++;
	} else {
	    game->water_excess -= use;
	    game->water_numyes++;
	}
    }

    /*
     * Garbage for landfill
     * 
     * Produces one garbage unit for every house and job
     */
    game->garbage_excess += tiles_gethouse(tiles, obj);
    game->garbage_excess += tiles_getnumemploy(tiles, obj);

}

extern int
utilities_one_power_production(int x, int y, mapobj_t obj)
{
    int use;

    if (!map_within_type(map, x, y, 3, MAPTYPE_ROAD, -1)) {
	return 0;
    }

    use = tiles_getpoweruse(tiles, obj);

    return (-1 * use);
}

static int
power_production_cb(int x, int y, void *data, float dist, void *rock)
{
    int *prod = (int *)rock;

    (*prod) += utilities_one_power_production(x, y, (mapobj_t)data);
    
    return 0;
}

static void
power_init(map_t *map)
{
    mapspot_list_t *plants;
    int production = 0;

    map_clearflag_wholemap(map, MAPFLAG_NOPOWER);
    game->power_numyes = 0;
    game->power_numno = 0;
    game->power_excess = 0;

    /* first calculate production */
    plants = map_find_tile_list(map, MAPTYPE_POWER);
    mapspot_iterate(plants, &power_production_cb, &production);

    game->power_excess = production;
}

static int
water_production_cb(int x, int y, void *data, float dist, void *rock)
{
    int use;

    use = tiles_getwateruse(tiles, (mapobj_t)data);
    if (use < 0) {
	game->water_excess += (-1 * use);
    }

    game->water_capacity += tiles_getcapacity(tiles, (mapobj_t)data);

    return 0;
}


static void
water_init(map_t *map)
{
    mapspot_list_t *plants;

    map_clearflag_wholemap(map, MAPFLAG_NOWATER);
    game->water_numyes = 0;
    game->water_numno = 0;
    game->water_capacity = 0;

    /* first calculate production */
    plants = map_find_tile_list(map, MAPTYPE_WATERUTIL);
    mapspot_iterate(plants, &water_production_cb, NULL);

}

static int
garbage_production_cb(int x, int y, void *data, float dist, void *rock)
{
    int capacity;
    mapspot_t spot;
    mapobj_t obj;

    capacity = tiles_getcapacity(tiles, (mapobj_t)data);
    if (capacity <= 0) return 0;

    if (game->garbage_excess < capacity) return 0;

    game->garbage_excess -= capacity;

    obj = map_item_name2obj("DumpFull");
    map_set_type(map, x, y, obj, 1);
    
    memset(&spot, 255, sizeof(mapspot_t));
    spot.mapobj = obj;
    connections_send_to_all("* BOARDSPOT %d %d %s\r\n",x,y,
			    map_spot2string(&spot));
    
    return 0;
}

static void
garbage_dealwith(map_t *map)
{
    mapspot_list_t *dumps;

    dumps = map_find_tile_list(map, MAPTYPE_LANDFILL);

    mapspot_iterate(dumps, &garbage_production_cb, NULL);
}

extern int
utilities_calculate(map_t *map, population_t *pop)
{
    int centerx = 0;
    int centery = 0;

    power_init(map);
    water_init(map);    

    /*
     * Now figure out usage (and potentially who doesn't get any)
     */
    population_center(pop, &centerx, &centery);    	    
    map_iterate(map, MAP_ITERATE_RADIAL, centerx, centery, 0,
		NULL, NULL,
		NULL, NULL,
		&use_cb, NULL);

    if (game->water_excess > game->water_capacity) {
	game->water_excess = game->water_capacity;
    }

    garbage_dealwith(map);

    return 0;
}
