package Cpanel::Easy::Utils::Configure;

# cpanel10 - Cpanel/Easy/Utils/Configure.pm  Copyright(c) 2005-2007 cPanel, Inc.
#                                                           All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cpanel license. Unauthorized copying is prohibited

use strict;
use warnings;
no warnings qw(redefine);

sub get_configure {
    my ( $self, $ns ) = @_;
    $ns = $self->headless_caller_ns() if !$ns;

    if ( !exists $self->{'configure'}{$ns} ) {

        my $fetch_ns = $ns;
        if ( $ns eq 'Cpanel::Easy::' . $self->{'state_config'}{'main_name'} ) {
            $fetch_ns .= '::' . $self->{'working_profile'}{ $self->{'state_config'}{'main_name'} }{'version'}
              if $self->{'working_profile'}{ $self->{'state_config'}{'main_name'} }{'version'};
        }

        if ( grep /^$ns$/, @{ $self->{'state_config'}{'include'} } ) {
            eval "use $ns;";
            if ( $ns->can('versions') ) {
              INC_VER:
                for my $v ( $ns->versions() ) {
                    my $v_ns = $ns . '::' . $v;
                    if ( $self->get_ns_value_from_profile( $v_ns, $self->{'working_profile'} ) ) {
                        $fetch_ns .= '::' . $v;
                        last INC_VER;
                    }
                }
            }
        }

        my $easyconfig = $self->get_easyconfig_hr_from_ns_via_state($fetch_ns);
        if ( !exists $easyconfig->{'configure'} ) {
            return;
        }
        else {
            $self->{'configure'}{$ns} = $easyconfig->{'configure'};
        }
    }

    return $self->{'configure'}{$ns};
}

sub set_configure {
    my ( $self, $hashref, $ns ) = @_;
    return if ref $hashref ne 'HASH';
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);

    $self->{'configure'}{$ns} = $hashref;
}

sub delete_from_configure {
    my ( $self, $keys_hr, $ns ) = @_;
    return if ref $keys_hr ne 'HASH';
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);

    for my $key ( keys %{$keys_hr} ) {
        if ( ref $keys_hr->{$key} eq 'CODE' ) {
            $self->{'configure'}{$ns}{$key} = [ grep { !$keys_hr->{$key}->( $key, $_ ) } @{ $self->{'configure'}{$ns}{$key} } ];
        }
        elsif ( ref $keys_hr->{$key} eq 'Regexp' ) {
            $self->{'configure'}{$ns}{$key} = [ grep { $_ !~ $keys_hr->{$key} } @{ $self->{'configure'}{$ns}{$key} } ];
        }
        elsif ( defined $keys_hr->{$key} ) {
            $self->{'configure'}{$ns}{$key} = [ grep { $_ ne $keys_hr->{$key} } @{ $self->{'configure'}{$ns}{$key} } ];
        }
        else {
            delete $self->{'configure'}{$ns}{$key};
        }
    }

    return 1;
}

sub replace_in_configure {
    my ( $self, $hashref, $ns ) = @_;
    return if ref $hashref ne 'HASH';
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);

    my %rem = map { $_ => undef } keys %{$hashref};
    $self->delete_from_configure( \%rem, $ns );

    for my $key ( keys %{$hashref} ) {
        $self->add_to_configure( { $key => $hashref->{$key} }, $ns );
    }
}

sub add_to_configure {
    my ( $self, $hashref, $ns ) = @_;
    return if ref $hashref ne 'HASH';
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);

    for my $key ( keys %{$hashref} ) {
        if ( $self->{'configure'}{$ns}{$key} ) {
            if ( ref $self->{'configure'}{$ns}{$key} ne 'ARRAY' ) {
                my $current = $self->{'configure'}{$ns}{$key};
                $self->{'configure'}{$ns}{$key} = [$current];
            }
            push @{ $self->{'configure'}{$ns}{$key} }, ref $hashref->{$key} eq 'ARRAY' ? @{ $hashref->{$key} } : $hashref->{$key};
        }
        else {
            if ( ref $hashref->{$key} eq 'ARRAY' ) {
                $self->{'configure'}{$ns}{$key} = $hashref->{$key};
            }
            else {
                $self->{'configure'}{$ns}{$key} = [ $hashref->{$key} ];
            }
        }
    }
}

sub get_configure_as_string {
    my ( $self, $ns ) = @_;
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);
    return join ' ', $self->get_configure_as_array($ns);
}

sub get_configure_as_array {
    my ( $self, $ns ) = @_;
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);

    my @conf =
      map {
        if ( ref $self->{'configure'}{$ns}{$_} ne 'ARRAY' ) {
            $_;
        }
        else {
            my @configure;
            my %seen;
            for my $value ( @{ $self->{'configure'}{$ns}{$_} } ) {
                my $string = $value ? "$_=$value" : $_;
                push @configure, $string if !exists $seen{$string};
                $seen{$string}++;
            }
            @configure = ($_) if !@configure;
            @configure;
        }
      }
      sort keys %{ $self->{'configure'}{$ns} };

    my @before = @conf;
    @conf = grep { defined $_ && $_ !~ /^\s*$/; } @conf;
    if ( @before != @conf ) {
        $self->print_alert( q{[info] '[_1]' configure had empty or whitespace only items: '[_2]'}, $ns, join( ',', @before ) );
    }

    return wantarray ? @conf : \@conf;
}

sub get_configure_as_hashref {
    my ( $self, $ns ) = @_;
    $ns = $self->headless_caller_ns() if !$ns;
    $self->get_configure($ns);
}

sub headless_caller_ns {
    my ($self) = @_;
    my $ns = caller(1);
    $ns =~ s{::\w+$}{};
    return $ns;
}

1;
