package Pcore::App::Controller::Ext;

use Pcore -role, -result;
use Pcore::Ext;
use Pcore::Share::WWW;
use WWW::CDN;
use Pcore::Util::Data qw[to_json];
use Pcore::Util::Text qw[mark_raw];

with qw[Pcore::App::Controller];

requires qw[ext_app ext_app_title];

has ext_default_theme_classic => ( is => 'ro', isa => Str, default => 'triton' );
has ext_default_theme_modern  => ( is => 'ro', isa => Str, default => 'triton' );
has ext_default_locale        => ( is => 'ro', isa => Str, default => 'en' );

sub BUILD ( $self, $args ) {
    Pcore::Ext->SCAN( $self->{app}, 'classic' );

    die qq[invalid Ext app] if !$Pcore::Ext::CFG->{app}->{ $self->ext_app };

    return;
}

# this method can be overrided in the child class
sub run ( $self, $req ) {
    if ( $req->{path_tail} && $req->{path_tail}->is_file ) {

        # try to return static content
        $self->return_static($req);
    }
    else {
        $req->(404)->finish;
    }

    return;
}

# TODO fix Ext overrides version
around run => sub ( $orig, $self, $req ) {

    # if path tail is not empty - fallback to the original method
    if ( $req->{path_tail} ) {

        # .js file request
        if ( $req->{path_tail} && $req->{path_tail} =~ /\A(.+)[.]js\z/sm ) {
            my $class = $Pcore::Ext::CFG->{class}->{ $Pcore::Ext::NS . $1 };

            if ( !$class ) {
                $req->(404)->finish;
            }
            else {
                $req->( 200, [ 'Content-Type' => 'application/javascript' ], $class->{js} )->finish;
            }

            return;
        }
        else {
            $self->$orig($req);
        }

        return;
    }

    my $resources = [];

    # FontAwesome
    push $resources->@*, WWW::CDN->fontawesome;

    # Ext framework
    my $ver       = 'v6.2.0';
    my $framework = 'classic';

    my $ext_resources;

    # get theme from query
    if ( $req->{env}->{QUERY_STRING} =~ /\btheme=([a-z-]+)/sm ) {
        my $theme = $1;

        $ext_resources = WWW::CDN->extjs( $ver, $framework, $theme, $self->{app}->{devel} );
    }

    # fallback to the default theme
    if ( !$ext_resources ) {
        my $theme = $framework eq 'classic' ? $self->ext_default_theme_classic : $self->ext_default_theme_modern;

        $ext_resources = WWW::CDN->extjs( $ver, $framework, $theme, $self->{app}->{devel} );
    }

    push $resources->@*, $ext_resources->@*;

    # Ext locale
    my $locale = $self->ext_default_locale;

    push $resources->@*, WWW::CDN->extjs_locale( $ver, $framework, $locale, $self->{app}->{devel} );

    # Ext overrides
    push $resources->@*, q[<script type="text/javascript" src="/static/ext/pcore/overrides-v6.js"></script>];

    my $loader_path = {
        q[*]     => '.',
        Pcore    => '.',
        Ext      => '/static/ext/src/',
        'Ext.ux' => '/static/ext/ux/',
    };

    $self->{app}->{api}->{map}->extdirect_map(
        $req->{host},
        undef, undef,
        sub ($api_map) {
            my $ext_app = $Pcore::Ext::CFG->{app}->{ $self->{ext_app} };

            my $data = {
                INDEX => {    #
                    title => $self->ext_app_title
                },
                resources => $resources,
                ext       => {
                    api_map => $api_map ? to_json($api_map)->$* : undef,
                    loader_path    => mark_raw( to_json( $loader_path, readable => $self->{app}->{devel} )->$* ),
                    app_namespace  => $Pcore::Ext::NS,
                    viewport_class => $ext_app->{viewport},
                    static_classes => undef,                           # TODO
                },
            };

            my $index = P->tmpl->render( 'ext/index.html', $data );

            $req->( 200, [ 'Content-Type' => 'text/html; charset=UTF-8' ], $index )->finish;

            return;
        }
    );

    return;
};

1;
## -----SOURCE FILTER LOG BEGIN-----
##
## PerlCritic profile "pcore-script" policy violations:
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
## | Sev. | Lines                | Policy                                                                                                         |
## |======+======================+================================================================================================================|
## |    3 | 21                   | ValuesAndExpressions::ProhibitInterpolationOfLiterals - Useless interpolation of literal string                |
## |------+----------------------+----------------------------------------------------------------------------------------------------------------|
## |    1 | 78                   | RegularExpressions::ProhibitEnumeratedClasses - Use named character classes ([a-z] vs. [[:lower:]])            |
## +------+----------------------+----------------------------------------------------------------------------------------------------------------+
##
## -----SOURCE FILTER LOG END-----
__END__
=pod

=encoding utf8

=head1 NAME

Pcore::App::Controller::Ext - ExtJS application HTTP controller

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 ATTRIBUTES

=head1 METHODS

=head1 SEE ALSO

=cut
