/*
* A map that looks like a circuit board.
*
* "Wells" are just big circles.
* "Pipes" are just lines that connect wells.
*
* Copyright (C) 2003, David Redick
* Released under the GNU General Public License (v2)
*/

#include <stdio.h>

#include "map.h"
#include "misc.h"

static char **grid;
static int *count;
static int size;

/******************************************************************************/
/*
* flip = 0 for front well connections
* flip = 1 for back well connections
*
* its just makes the map look & play better
*/

static void
draw_pipe (int fromr, int fromc, int tor, int toc, int flip)
{
  int fromx, fromy, tox, toy;


  if (fromc < toc)
    {
      /* up/down then across */
      if (flip == 0)
        {
          /* go up/down to reach target */
          section_center (&fromx, &fromy, fromr, fromc);
          section_center (&tox, &toy, tor, fromc);
          rectfill (map.map, fromx - size, fromy, tox + size, toy, 255);

          /* across some num of sections */
          section_center (&fromx, &fromy, tor, fromc);
          section_center (&tox, &toy, tor, toc);
          rectfill (map.map, fromx, fromy - size, tox, toy + size, 255);
        }
      /* across then up/down */
      else
        {
          /* across some num of sections */
          section_center (&fromx, &fromy, fromr, fromc);
          section_center (&tox, &toy, fromr, toc);
          rectfill (map.map, fromx, fromy - size, tox, toy + size, 255);

          /* go up/down to reach target */
          section_center (&fromx, &fromy, fromr, toc);
          section_center (&tox, &toy, tor, toc);
          rectfill (map.map, fromx - size, fromy, tox + size, toy, 255);
        }
    }
  else if (fromc > toc)
    {
      /* across then up/down */
      if (flip == 0)
        {
          /* across some num of sections */
          section_center (&fromx, &fromy, fromr, fromc);
          section_center (&tox, &toy, fromr, toc);
          rectfill (map.map, fromx, fromy - size, tox, toy + size, 255);

          /* go up/down to reach target */
          section_center (&fromx, &fromy, fromr, toc);
          section_center (&tox, &toy, tor, toc);
          rectfill (map.map, fromx - size, fromy, tox + size, toy, 255);
        }
      /* up/down then across */
      else
        {
          /* go up/down to reach target */
          section_center (&fromx, &fromy, fromr, fromc);
          section_center (&tox, &toy, tor, fromc);
          rectfill (map.map, fromx - size, fromy, tox + size, toy, 255);

          /* across some num of sections */
          section_center (&fromx, &fromy, tor, fromc);
          section_center (&tox, &toy, tor, toc);
          rectfill (map.map, fromx, fromy - size, tox, toy + size, 255);
        }
    }
  else
    {
      /* go up/down to reach target */
      section_center (&fromx, &fromy, fromr, fromc);
      section_center (&tox, &toy, tor, toc);
      rectfill (map.map, fromx - size, fromy, tox + size, toy, 255);
    }

  return;
}

/******************************************************************************/
/* connect all wells on in row */

static void
connect_rows ()
{
  int r, c;
  int fromc, toc;

  /* make gcc shutup about these being uninitialized */
  fromc = toc = -1;


  for (r = 0; r < map.num_row; r++)
    {
      /* can't connect if there's not 2 or more... */
      if (count[r] < 2)
        continue;

      fromc = -1;
      /* find first c... */
      for (c = 0; c < map.num_col; c++)
        {
          if (grid[r][c] == 1)
            {
              fromc = c;
              break;
            }
        }

      toc = -1;
      /* find last c... */
      for (c++; c < map.num_col; c++)
        {
          if (grid[r][c] == 1)
            toc = c;
        }

      /* Defensive check: ensure we found valid wells */
      if (fromc >= 0 && toc >= 0)
        draw_pipe (r, fromc, r, toc, 0);
    }


  return;
}

/******************************************************************************/
/* connect the first well on each row */
/* TODO: I don't think this works 100% */

static void
connect_front ()
{
  int r, c;
  int fromr, fromc, tor, toc;

  /* make gcc shutup about these being uninitialized */
  fromc = tor = toc = -1;


  for (r = 0; r < map.num_row; r++)
    {
      if (count[r] == 0)
        continue;

      fromr = r;
      fromc = -1;
      /* find first well */
      for (c = 0; c < map.num_col; c++)
        {
          if (grid[fromr][c] == 1)
            {
              fromc = c;
              break;
            }
        }

      tor = -1;
      /* find next row with a well */
      for (r++; r < map.num_row; r++)
        {
          if (count[r] > 0)
            {
              tor = r;
              break;
            }
        }
      /* there might be no other wells after from row */
      if (r == map.num_row)
        break;

      toc = -1;
      /* find first well on to row */
      for (c = 0; c < map.num_col; c++)
        {
          if (grid[tor][c] == 1)
            {
              toc = c;
              break;
            }
        }

      /* Defensive check: ensure we found valid wells */
      if (fromc >= 0 && tor >= 0 && toc >= 0)
        {
          draw_pipe (fromr, fromc, tor, toc, 0);
          printf ("FRONT: %d, %d ---- %d, %d\n", fromr, fromc, tor, toc);
        }
      r = tor - 1;
    }

  return;
}

/******************************************************************************/
/* connect the last well on each row */
/* TODO: I don't think this works 100% */

static void
connect_back ()
{
  int r, c;
  int fromr, fromc, tor, toc;


  /* make gcc shutup about these being uninitialized */
  fromc = tor = toc = -1;


  for (r = 0; r < map.num_row; r++)
    {
      if (count[r] == 0)
        continue;

      fromr = r;
      fromc = -1;
      /* find last well */
      for (c = map.num_col - 1; c >= 0; c--)
        {
          if (grid[fromr][c] == 1)
            {
              fromc = c;
              break;
            }
        }

      tor = -1;
      /* find next row with well */
      for (r++; r < map.num_row; r++)
        {
          if (count[r] > 0)
            {
              tor = r;
              break;
            }
        }
      /* there might not be another row after from row */
      if (r == map.num_row)
        break;

      toc = -1;
      /* find last well */
      for (c = map.num_col - 1; c >= 0; c--)
        {
          if (grid[tor][c] == 1)
            {
              toc = c;
              break;
            }
        }

      /* Defensive check: ensure we found valid wells */
      if (fromc >= 0 && tor >= 0 && toc >= 0)
        {
          draw_pipe (fromr, fromc, tor, toc, 1);
          printf ("BACK: %d, %d ---- %d, %d\n", fromr, fromc, tor, toc);
        }
      r = tor - 1;
    }

  return;
}

/******************************************************************************/

void
connect_mid ()
{
  int r, c;
  int fromr, fromc, tor, toc;
  int mid, i;


  /* make gcc shutup about these being uninitialized */
  fromc = tor = toc = -1;


  for (r = 0; r < map.num_row; r++)
    {
      printf ("row == %d, count[%d] = %d\n", r, r, count[r]);
      if (count[r] == 0)
        continue;

      fromr = r;

      fromc = -1;
      /* find first middle well */
      mid = count[fromr] / 2;
      i = 0;
      for (c = 0; c < map.num_col; c++)
        {
          if (grid[fromr][c] == 1)
            {
              fromc = c;
              if (i == mid)
                break;
              i++;
            }
        }

      tor = -1;
      /* find to row */
      for (r++; r < map.num_row; r++)
        {
          if (count[r] > 0)
            {
              tor = r;
              break;
            }
        }
      /* there might not be another row after from row */
      if (r == map.num_row)
        break;

      toc = -1;
      /* find first middle well */
      mid = count[tor] / 2;
      i = 0;
      printf ("count[tor]/2 == %d/2 == %d\n", count[tor], mid);
      for (c = 0; c < map.num_col; c++)
        {
          if (grid[tor][c] == 1)
            {
              toc = c;
              if (i == mid)
                break;
              i++;
            }
        }

      /* Defensive check: ensure we found valid wells */
      if (fromc >= 0 && tor >= 0 && toc >= 0)
        {
          draw_pipe (fromr, fromc, tor, toc, 0);
          printf ("pipe= %d, %d --- %d, %d\n", fromr, fromc, tor, toc);
        }
      r = tor - 1;
    }
}

/******************************************************************************/

void
circuit ()
{
  int r, c;
  int do_cut;
  int radius;
  int centerx, centery;


  clear_invert_map ();

  grid = (char **) create_grid (map.num_row, map.num_col, sizeof (char));
  count = (int *) create_array (map.num_row, sizeof (int));

  radius =
    (map.sec_width > map.sec_height ? map.sec_width : map.sec_height) / 4.0;
  radius = (radius == 0 ? 1 : radius);

  size =
    (map.sec_width > map.sec_height ? map.sec_width : map.sec_height) / 12.0;
  size = (size == 0 ? 1 : size);

  for (r = 0; r < map.num_row; r++)
    {
      count[r] = 0;
      for (c = 0; c < map.num_col; c++)
        {
          if ((r == 0 || r == map.num_row - 1)
              && (c == 0 || c == map.num_col / 2 || c == map.num_col - 1))
            do_cut = 1;
          else
            do_cut = rand () % 4;

          if (do_cut != 1)
            {
              grid[r][c] = 0;
              continue;
            }

          section_center (&centerx, &centery, r, c);
          circlefill (map.map, centerx, centery, radius, 255);

          grid[r][c] = 1;
          count[r]++;
        }
    }


  connect_rows ();
  connect_front ();
  connect_back ();
  connect_mid ();

  delete_grid ((void **) grid, map.num_row);
  delete_array (count);

  /* redraw outline */
  /* TODO: once in a while if cuts off the edge.. */
  rect (map.map, 0, 0, map.width - 1, map.height - 1, 0);

  return;
}
