#!/usr/bin/perl
use strict;
use warnings;
use lib "../adv";
use include;

# CONFIGURATION
my $unit_size = 10;     # [small], [large]
my $area = "halls";      # beard, halls, squiggle
my $formation = "flank"; # line, troop, flank
my $mode = "single";   # single, multi

# SET UP UI
use HexedUI;
my $ui = create HexedUI {
  Main => {
    Type   => "Map",
    At     => [0, 0],
    Size   => ["100%", "100%"],
    Border => 1,
    Render => sub {
      my $tile = shift;
      my ($char, $color);
      if (ref $tile->{_}) {
        ($char, $color) = $tile->{_}->symbol;
      } elsif ($tile->{color}) {
        $char = $tile->{_};
        $color = $tile->{color};
      } else {
        $char = $tile->{_};
        $color = {
          "#" => "orange",
          "." => "grey"
        }->{$char};
        $color ||= "yellow";
      }
      return ord($char) | HexedUI::paint($color);
    }
  },
};
GAME->{UI} = $ui;

# SET UP MAP
use BDSM::Transform;
my $map = loadmap("../maps/$area");
$ui->{Main}->setup($map);
$map->{OnChange} = sub {
  my ($map, $y, $x, $new) = @_;
  $ui->{Main}->_mod($y, $x, $map->{Map}[$y][$x]);
};
use Highway;
preprock($map);

sub run {
  # Initialize units
  use Unit;
  my @units;
  # Rnd Starting Positions: CONFIG->rndload($file);
  GAME->{UnitSize} = $unit_size;  # leader needs to know to make room
  foreach (1 .. $unit_size) {
    my $unit = GAME->{Classes}{Unit}->new(Map => $map, Num => $_);
    if ($_ == 1) {
      $unit->{Magnet}{Last} = "h";
    } else {
      $unit->{Magnet}{Buddy} = $units[$_ - 2];
      # Whilst assembling, just form a line.
      $unit->{Magnet}{Dir} = [0, 1];
    }
    push @units, $unit;
  }

  # PART ONE: Assembly

  # Single: Find the highway and then our buddy, then give control to next unit.
  # Multi: Everybody find the highway at once. If our buddy is on too, find
  # them; otherwise wait.

  my %found;
  while (1) {
    my $cntr = 0;
    foreach my $unit (@units) {
      if ($mode eq "single") {
        1 until $unit->gethi;
        1 until $unit->assemble == 42 and $unit->{Laster} = [$unit->{Y}, $unit->{X}];
        $cntr++;
      } else {
        $unit->gethi and $found{ $unit->{Num} }++ unless $found{ $unit->{Num} };
        next unless $found{ $unit->{Num} };
        $unit->assemble == 42 and $unit->{Laster} = [$unit->{Y}, $unit->{X}] and $cntr++;
      }
    }
    last if $cntr == @units;
  }

  # INTERMISSION

  if ($formation eq "flank") {
    # We had to assemble normally in a line. But now we need to reassign
    # buddies cause this formation is really funky.
    # #2 is an anchor. So is another. Just assign group numbers.
    my $mid = int($#units / 2) + 1; # My magic number.
    foreach my $num (1 .. $#units) {
      if ($num < $mid) {
        $units[$num]->{Magnet}{Group} = 1;
      } elsif ($num == $mid) {
        # We're the 2nd anchor.
        $units[$num]->{Magnet}{Group} = 2;
        $units[$num]->{Magnet}{Buddy} = $units[0];
      } else {
        $units[$num]->{Magnet}{Group} = 2;
      }
    }
  }

  # PART TWO: Movement

  # Single & Multi: Follow our buddy until everybody reaches the destination.

  while (1) {
    GAME->{UI}{Main}->draw;
    foreach my $unit (@units) {
      ($unit->{Num} == 1) ? ctrl(@units) : $unit->magnet();
    }
  }
}

sub ctrl {
  my $me = shift;
  my @units = @_;

  my $in = lc GAME->{UI}->input;
  return if $in eq "x";
  return unless $in =~ m/[hjklyubn]/;
  my ($y, $x) = ($me->{Y}, $me->{X});
  $x-- if $in eq "h" or $in eq "y" or $in eq "b";
  $y++ if $in eq "j" or $in eq "b" or $in eq "n";
  $y-- if $in eq "k" or $in eq "y" or $in eq "u";
  $x++ if $in eq "l" or $in eq "u" or $in eq "n";
  $me->go($y, $x);

  # Update the vectors for the troops.
  if ($formation eq "line") {
    $_->{Magnet}{Dir} = {
      l => [0, -1],
      h => [0, +1],
      k => [+1, 0],
      j => [-1, 0],
      y => [+1, +1],
      u => [+1, -1],
      b => [-1, +1],
      n => [-1, -1],
    }->{$in} foreach @units;
  } elsif ($formation eq "troop") {
    # This is the anchor's
    $units[0]->{Magnet}{Dir} = {
      l => [-3, -5],
      h => [-3, +5],
      k => [+3, -5],
      j => [-3, -5],
      y => [-3, +10],
      u => [-3, -10],
      b => [-7, +5],
      n => [-5, +1],
    }->{$in};
    # And these for the others
    $_->{Magnet}{Dir} = {
      l => [+1, 0],
      h => [+1, 0],
      k => [0, +1],
      j => [0, +1],
      y => [+1, -1],
      u => [+1, +1],
      b => [+1, +1],
      n => [+1, -1],
    }->{$in} foreach @units[1 .. $#units];
  } elsif ($formation eq "flank") {
    foreach (@units) {
      $_->{Magnet}{Dir} = {
        l => [-1, -1],
        h => [-1, +1],
        k => [+1, -1],
        j => [-1, -1],
        y => [-1, +1],
        u => [-1, -1],
        b => [-1, -1],
        n => [-1, +1]
      }->{$in} if $_->{Magnet}{Group} == 1;
      $_->{Magnet}{Dir} = {
        l => [+1, -1],
        h => [+1, +1],
        k => [+1, +1],
        j => [-1, +1],
        y => [+1, -1],
        u => [+1, +1],
        b => [+1, +1],
        n => [+1, -1]
      }->{$in} if $_->{Magnet}{Group} == 2;
    }
  }
}

run;
