package QBit::WebInterface::Controller::BEMHTML::Wizard;

use qbit;

use base qw(QBit::Class);

use QBit::WebInterface::Controller::BEMHTML::Wizard::Form;

__PACKAGE__->mk_ro_accessors(qw(steps controller));

sub process {
    my ($self) = @_;

    return $self->denied($self->controller)
      if exists($self->{'check_rights'}) && !$self->controller->check_rights(@{$self->{'check_rights'}});

    $self->{'cur_tab'} = 0;
    my $prev_step;
    foreach my $step (@{$self->steps}) {
        $step->{'fields'} = [$step->{'fields'}($self)] if ref($step->{'fields'}) eq 'CODE';
        push(@{$step->{'fields'}}, {name => 'wizard_stage', type => 'hidden', value => $self->{'cur_tab'} + 1});

        if ($prev_step) {
            foreach my $field (@{$prev_step->{'fields'}}) {
                push(
                    @{$step->{'fields'}},
                    {%$field, value => $prev_step->{'__FORM__'}->get_value($field->{'name'}), hidden => 1}
                );
            }
        }

        $step->{'__FORM__'} = $self->{'__FORM__'} = QBit::WebInterface::Controller::BEMHTML::Wizard::Form->new(
            (map {$_ => $step->{$_}} grep {exists($step->{$_})} qw(fields check template vars)),
            controller => $self->controller);

        $self->{'form_content'} =
          $self->{'__FORM__'}
          ->process(no_save => $self->{'cur_tab'} == $self->controller->request->param('wizard_stage', 0));
        $self->{'form_content'} = ${$self->{'form_content'}} if ref($self->{'form_content'}) eq 'SCALAR';

        last
          if $self->{'cur_tab'} == $self->controller->request->param('wizard_stage', 0)
              || $self->{'__FORM__'}->{'__ERROR__'}
              || keys(%{$self->{'__FORM__'}->{'__FIELDS_ERROR__'}});

        $prev_step = $step;
        $self->{'cur_tab'}++;
    }

    if ($self->{'cur_tab'} < @{$self->steps}) {
        return $self->controller->request->param('ajax')
          ? $self->controller->as_json(
            {
                content   => $self->controller->_bemjson2data($self->{'form_content'}),
                stage     => $self->{'cur_tab'},
                tab_names => $self->step_names
            }
          )
          : $self->controller->from_bem_template('common/wizard.bem.tt2',
            vars => {%{$self->{'vars'} || {}}, wizard => $self});
    }

    $self->{'save'}($self) if $self->{'save'} && ref($self->{'save'}) eq 'CODE';

    $self->{'redirect_opts'} ||= {};

    my $retpath = $self->controller->request->param('retpath');

    if ($self->controller->request->param('ajax')) {
        if ($retpath) {
            return $self->controller->as_json(
                {
                    action => 'redirect',
                    url    => $self->controller->_get_url_absolute($retpath),
                }
            );
        } else {
            return $self->controller->as_json(
                {
                    action => 'redirect',
                    url    => $self->controller->app->make_cmd(
                        $self->{'redirect'},
                        delete($self->{'redirect_opts'}{'path'}),
                        %{$self->{'redirect_opts'}}
                    )
                }
            );
        }
    } else {
        if ($retpath) {
            return $self->controller->redirect2url_internal($retpath);
        } else {
            return $self->controller->redirect($self->{'redirect'}, %{$self->{'redirect_opts'}});
        }
    }
}

sub step_names {
    my ($self) = @_;

    return [map {$_->{'title'}} @{$self->steps}];
}

sub get_field_names {
    my ($self, @params) = @_;

    return $self->{'__FORM__'} ? $self->{'__FORM__'}->get_field_names(@params) : undef;
}

sub get_value {
    my ($self, @params) = @_;

    return $self->{'__FORM__'} ? $self->{'__FORM__'}->get_value(@params) : undef;
}

sub denied {return $_[1]->denied()}

1;
