package Ifweb;

use strict;
use warnings;

use Dancer ':syntax';

use Ifweb::Iwconfig;
use Ifweb::Ifupdown;

use Authen::Simple::PAM;
use MIME::Base64;

our $VERSION = '0.1';

sub auth_basic {
    my ($redirect) = @_;

    # Get authentication data from request
    my $auth = request->header('Authorization');

    my $authorized = undef;

    if (defined $auth && $auth =~ /^Basic (.*)$/) {
        my ($user, $password) = split(/:/, (MIME::Base64::decode($1) || ":"));

        my $pam = Authen::Simple::PAM->new(
            service => 'Ifweb',
            );

        my ($name, $passwd, $gid, $members) = getgrnam('netdev');
        my @members = split(/\s+/, $members);

        if ($pam->authenticate($user, $password)) {
            if ($user eq "root" || grep(/$user/, @members)) {
                return 1;
            }
        }
    }

    my $content = "Authorization required: access restricted to members of the netdev group.";
    return halt(Dancer::Response->new(
                    status => 401,
                    content => $content,
                    headers => [
                        'Content-Type' => 'text/plain',
                        'Content-Length' => length($content),
                        'WWW-Authenticate' => 'Basic realm="netdev group"'
                    ]
                ));
}

hook 'before' => sub {
    auth_basic request->path_info;
};

get '/' => sub {
    my $states   = Ifweb::Ifupdown::ifstate;
    my $networks = Ifweb::Ifupdown::networks;
    my $ifaces   = Ifweb::Ifupdown::ifaces;

    my $iface = config->{wlan_iface};
    my $cells = Ifweb::Iwconfig::scan($iface);

    if (defined(session->{msg_seen}) && session->{msg_seen}) {
        session info     => undef;
        session error    => undef;
        session question => undef;
        session msg_seen => false;
    }
    else {
        session msg_seen => true;
    }

    template 'index' => {
        messages => template('messages',
                             { info     => session->{info},
                               error    => session->{error},
                               question => session->{question}, },
                             { layout => undef }),
        status   => template('status',
                             { states => $states },
                             { layout => undef }),
        networks => template('networks',
                              { networks => $networks,
                                ifaces   => $ifaces },
                              { layout => undef }),
        scan     => template('scan',
                             { iface => $iface,
                               cells => $cells},
                             { layout => undef }),
    };
};

get '/up' => sub {
    my $phy = params->{phy};
    my $log = params->{log};

    if (Ifweb::Ifupdown::up($phy, $log)) {
        session info     => "Interface $phy enabled with configuration $log.";
        session error    => undef;
        session question => undef;
        session msg_seen => false;
    }
    else {
        session info     => undef;
        session error    => "Failed to enable interface $phy with configuration $log.";
        session question => undef;
        session msg_seen => false;
    }
    
    redirect '/';
};

get '/down' => sub {
    my $phy = params->{phy};

    Ifweb::Ifupdown::down($phy);

    session info     => "Interface $phy disabled.";
    session error    => undef;
    session question => undef;
    session msg_seen => false;
    redirect '/';
};

get '/scan' => sub {
    my $iface = "wlan0";
    my $cells = Ifweb::Iwconfig::scan($iface);

    template 'scan' => {
        iface => $iface,
        cells => $cells,
    };
};

get '/networks' => sub {
    my $networks = Ifweb::Ifupdown::networks;
    my $ifaces   = Ifweb::Ifupdown::ifaces;

    template 'networks' => {
        networks => $networks,
        ifaces   => $ifaces,
    };
};

get '/select' => sub {
    my $id = params->{id};
    my $cell = session->{cells}->[$id];

    my $essid = $cell->{ESSID};
    my $encryption = $cell->{encryption};
    my $key = "key";

    my $interfaces = Ifweb::Ifupdown::config_template
        $cell,
        "<span class=\"name\">$essid</span>",
        "<span class=\"key\">$key</span>",
        ;

    template 'select' => {
        messages => template('messages',
                             { info     => session->{info},
                               error    => session->{error},
                               question => session->{question}, },
                             { layout => undef }),
        id             => $id,
        cell           => $cell,
        essid          => $cell->{ESSID},
        encryption     => $encryption,
        interfaces     => $interfaces,
        key            => $key,
    }
};

post '/add' => sub {
    my $id   = params->{id};
    my $name = params->{name};
    my $key  = params->{key};

    my $cell = session->{cells}->[$id];
    my $essid      = $cell->{ESSID};
    my $encryption = $cell->{encryption};
    my $iface      = $cell->{iface};

    my $interfaces = Ifweb::Ifupdown::config_template
        $cell,
        $name,
        $key;

    my $interfaces_file = config->{interfaces_file};

    print STDERR $interfaces_file, ":\n";
    print STDERR $interfaces, "\n";
    open(my $file_if, '>>', $interfaces_file);
    print $file_if $interfaces;
    close($file_if);

    session info     => "Network $name successfully added for ESSID $essid.";
    session error    => undef;
    session question => {text => "Do you want to bring it up now ?", yes => "<a href=\"/up?phy=$iface&log=$name\">Yes</a>"};
    session msg_seen => false;

    redirect '/';
};

true;
