package LasTres::Area;

use v5.36.0;

use strict;
use warnings;

use feature 'signatures';

use Moo::Role;
use LasTres::Battle;
use LasTres::EnemyTeam;
use LasTres::Util;

requires qw/identifier locations name parent/;
has children => (
    is      => 'ro',
    lazy    => 1,
    builder => \&_build_children,
);

## OVERRIDE
# If true the entire map will be discovered when you step into the Area.
sub get_auto_discover ($self) {
    return 0;
}

## OVERRIDE
# The number of intervals of 10 seconds until you can reach
# other location.
sub frames_to_move ($self) {
    return 5;
}

## OVERRIDE
# The number of intervals of 10 seconds until you can
# possibly discover a new location when exploring.
sub frames_to_explore ($self) {
    return 7;
}

## OVERRIDE
# Whenever wild enemies will appear on explore or move.
sub has_movement_auto_combat ($self) {
    return 0;
}

## OVERRIDE
# The minimum number of enemies that will appear for every PJ
# when a battle is determined to take place on movement.
# Adjustable to the $pj, you should be careful with it being undef.
sub min_enemies_per_head ($self, $pj = undef) {
    return 1;
}

## OVERRIDE
# The maximum number of enemies that will appear for every PJ
# when a battle is determined to take place on movement.
# Adjustable to the $pj, you should be careful with it being undef.
sub max_enemies_per_head ($self, $pj = undef) {
    return 1;
}

## OVERRIDE
# The list of possible enemies on random encounter exploring or moving.
# You can adjust them to the level of the player using the $pj variable.
# Beware that this can be undef. 
sub list_of_enemies ( $self, $pj = undef ) {
    return [];
}

## OVERRIDE
# The percentual chance of random combat encounter on movement or explore.
sub chance_combat ($self) {
    return 50;
}

## OVERRIDE (Always use $self->SUPER::on_move_explore_frame($self, $team).)
# What to on movement and explore frame.
# You can use this to make the user encounter drops for example, but if you
# do not call the SUPER function you will lose functionality.
sub on_move_explore_frame ( $self, $team ) {
    return if $self->_try_to_start_battle($team);
}

sub _try_to_start_battle ( $self, $team ) {
    require LasTres::Redis;
    my $redis      = LasTres::Redis->new;
    if ( !$self->has_movement_auto_combat ) {
        ## Combat not enabled.
        return 0;
    }
    my $dice_result = LasTres::Util::rand_range_int( 0, 100 );
    if ( $dice_result > $self->chance_combat ) {
        ## No combat in this frame by RNG choice.
        return 0;
    }
    ## Creating enemy team.
    my $battle = LasTres::Battle->new( team1 => $team, last_frame => 0 );
    my $team2  = LasTres::EnemyTeam->new( current_battle => $battle->uuid );
    my @enemy_members = @{$self->_generate_enemies_team($team)};
    if ( !scalar @enemy_members ) {
        ## No enemies generated.
        return 0;
    }
    LasTres::Battle->start_battle_machine($team, \@enemy_members);
    return 1;
}

sub _generate_enemies_team ($self, $team) {
    my @enemy_members_array;
    for my $pj ( @{$team->combat_members} ) {
        my $number_of_enemies =
          LasTres::Util::rand_range_int( $self->min_enemies_per_head($pj),
            $self->max_enemies_per_head($pj) );
        $self->_generate_n_enemies_pj( $number_of_enemies, \@enemy_members_array, $pj );
    }
    return \@enemy_members_array;
}

sub _generate_n_enemies_pj ( $self, $number_of_enemies,
    $enemy_members_array, $pj )
{
    my @list_possible_enemies = @{ $self->list_of_enemies($pj) };
    if ( !scalar @list_possible_enemies ) {
        warn "$self does not have defined enemies.";
        return;
    }
    for ( my $i = 0 ; $i < $number_of_enemies ; $i++ ) {
        my $choice_enemy_index =
          LasTres::Util::rand_range_int( 0, $#list_possible_enemies );
        my $choice_enemy = $list_possible_enemies[$choice_enemy_index];
        push @$enemy_members_array, $choice_enemy;
    }
}

## OVERRIDE
# Determines if the explore functionality is enabled for this area.
sub can_explore {
    return 1;
}

sub _build_children ($self) {
    my $locations = $self->locations;
    my @locations = map { $locations->{$_} } keys %$locations;
    @locations = sort { $a->name cmp $b->name } @locations;
    return \@locations;
}
1;
