# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.

package LJ::Widget::ThemeNav;

use strict;
use base qw(LJ::Widget);
use Carp qw(croak);
use LJ::Customize;

sub ajax               { 1 }
sub can_fake_ajax_post { 1 }
sub authas             { 1 }
sub need_res           { qw( stc/widgets/themenav.css js/6alib/inputcomplete.js ) }

sub render_body {
    my $class = shift;
    my %opts  = @_;

    my $u = $class->get_effective_remote();
    die "Invalid user." unless LJ::isu($u);

    my $theme_chooser_id = defined $opts{theme_chooser_id} ? $opts{theme_chooser_id} : 0;
    my $headextra        = $opts{headextra};

    my $remote   = LJ::get_remote();
    my $getextra = $u->user ne $remote->user ? "?authas=" . $u->user : "";
    my $getsep   = $getextra ? "&" : "?";

    # filter criteria
    my $cat      = defined $opts{cat}      ? $opts{cat}         : "";
    my $layoutid = defined $opts{layoutid} ? $opts{layoutid}    : 0;
    my $designer = defined $opts{designer} ? $opts{designer}    : "";
    my $search   = defined $opts{search}   ? $opts{search}      : "";
    my $page     = defined $opts{page}     ? $opts{page}        : 1;
    my $show     = defined $opts{show}     ? $opts{show}        : 12;
    my $showarg  = $show != 12             ? "show=$opts{show}" : "";

    # we want to have "All" selected if we're filtering by layout or designer, or if we're searching
    my $viewing_all = $layoutid || $designer || $search;

    my $theme_chooser = LJ::Widget::ThemeChooser->new( id => $theme_chooser_id );
    $theme_chooser_id = $theme_chooser->{id} unless $theme_chooser_id;
    $$headextra .= $theme_chooser->wrapped_js( page_js_obj => "Customize" ) if $headextra;

    # sort cats by specificed order key, then alphabetical order
    my %cats = LJ::Customize->get_cats($u);
    my @cats_sorted =
        sort { $cats{$a}->{order} <=> $cats{$b}->{order} }
        sort { lc $cats{$a}->{text} cmp lc $cats{$b}->{text} } keys %cats;

    # pull the main cats out of the full list
    my @main_cats_sorted;
    for ( my $i = 0 ; $i < @cats_sorted ; $i++ ) {
        my $c = $cats_sorted[$i];

        if ( defined $cats{$c}->{main} ) {
            my $el = splice( @cats_sorted, $i, 1 );
            push @main_cats_sorted, $el;
            $i--;    # we just removed an element from @cats_sorted
        }
    }

    my @keywords        = LJ::Customize->get_search_keywords_for_js($u);
    my $keywords_string = join( ",", @keywords );

    my $upsell = LJ::Hooks::run_hook( 'customize_advanced_area_upsell', $u ) || '';

    my $main_cat_list = $class->print_cat_list(
        user         => $u,
        selected_cat => $cat,
        viewing_all  => $viewing_all,
        cat_list     => \@main_cats_sorted,
        getextra     => $getextra,
        showarg      => $showarg,
    );

    my $cat_list = $class->print_cat_list(
        user         => $u,
        selected_cat => $cat,
        viewing_all  => $viewing_all,
        cat_list     => \@cats_sorted,
        getextra     => $getextra,
        showarg      => $showarg,
    );

    my $themechooser_html = $theme_chooser->render(
        'cat'      => $cat,
        'layoutid' => $layoutid,
        'designer' => $designer,
        'search'   => $search,
        'page'     => $page,
        'show'     => $show
    );

    my $vars = {
        cat               => $cat,
        layoutid          => $layoutid,
        designer          => $designer,
        search            => $search,
        page              => $page,
        show              => $show,
        themechooser_html => $themechooser_html,
        keywords_string   => $keywords_string,
        upsell            => $upsell,
        cats_sorted       => \@cats_sorted,
        main_cat_list     => $main_cat_list,
        cat_list          => $cat_list
    };

    return DW::Template->template_string( 'widget/themenav.tt', $vars );
}

sub print_cat_list {
    my $class = shift;
    my %opts  = @_;

    my $u        = $opts{user};
    my $cat_list = $opts{cat_list};

    my %cats = LJ::Customize->get_cats($u);

    my @special_themes       = LJ::S2Theme->load_by_cat("special");
    my $special_themes_exist = 0;
    foreach my $special_theme (@special_themes) {
        my $layout_is_active =
            LJ::Hooks::run_hook( "layer_is_active", $special_theme->layout_uniq );
        my $theme_is_active = LJ::Hooks::run_hook( "layer_is_active", $special_theme->uniq );

        if ( $layout_is_active && $theme_is_active ) {
            $special_themes_exist = 1;
            last;
        }
    }

    my @custom_themes = LJ::S2Theme->load_by_user( $opts{user} );

    my $ret;

    for ( my $i = 0 ; $i < @$cat_list ; $i++ ) {
        my $c = $cat_list->[$i];

        next if $c eq "special" && !$special_themes_exist;
        next if $c eq "custom"  && !@custom_themes;

        my $li_class = "";
        $li_class .= " on"
            if ( $c eq $opts{selected_cat} )
            || ( $c eq "featured" && !$opts{selected_cat} && !$opts{viewing_all} )
            || ( $c eq "all" && $opts{viewing_all} );
        $li_class .= " first" if $i == 0;
        $li_class .= " last"  if $i == @$cat_list - 1;
        $li_class =~ s/^\s//;    # remove the first space
        $li_class = " class='$li_class'" if $li_class;

        my $arg = "";
        $arg = "cat=$c" unless $c eq "featured";
        if ( $arg || $opts{showarg} ) {
            my $allargs = $arg;
            $allargs .= "&" if $allargs && $opts{showarg};
            $allargs .= $opts{showarg};
            $arg = $opts{getextra} ? "&$allargs" : "?$allargs";
        }

        $ret .=
"<li$li_class><a href='$LJ::SITEROOT/customize/$opts{getextra}$arg' class='theme-nav-cat'>$cats{$c}->{text}</a></li>";
    }

    return $ret;
}

sub handle_post {
    my $class = shift;
    my $post  = shift;
    my %opts  = @_;

    my $q_string = BML::get_query_string();
    $q_string =~ s/&?page=\d+//g;

    my $url = "$LJ::SITEROOT/customize/";
    if ( $post->{filter} ) {
        $q_string = "?$q_string" if $q_string;
        my $q_sep = $q_string ? "&" : "?";
        $url .= $q_string;

    }
    elsif ( $post->{page} ) {
        $q_string = "?$q_string" if $q_string;
        my $q_sep = $q_string ? "&" : "?";

        $post->{page} = LJ::eurl( $post->{page} );
        if ( $post->{page} != 1 ) {
            $url .= "$q_string${q_sep}page=$post->{page}";
        }
        else {
            $url .= $q_string;
        }
    }
    elsif ( $post->{show} ) {
        $q_string =~ s/&?show=\w+//g;
        $q_string = "?$q_string" if $q_string;
        my $q_sep = $q_string ? "&" : "?";

        $post->{show} = LJ::eurl( $post->{show} );
        if ( $post->{show} != 12 ) {
            $url .= "$q_string${q_sep}show=$post->{show}";
        }
        else {
            $url .= $q_string;
        }
    }
    elsif ( $post->{search} ) {
        my $show   = ( $q_string =~ /&?show=(\w+)/ )   ? "&show=$1"   : "";
        my $authas = ( $q_string =~ /&?authas=(\w+)/ ) ? "&authas=$1" : "";
        $q_string = "";

        $post->{search} = LJ::eurl( $post->{search} );
        $url .= "?search=$post->{search}$authas$show";
    }

    return BML::redirect($url);
}

sub js {
    q [
        initWidget: function () {
            var self = this;

            if ($('search_box')) {
                var keywords = new InputCompleteData(Customize.ThemeNav.searchwords, "ignorecase");
                var ic = new InputComplete($('search_box'), keywords);

                var text = "theme, layout, or designer";
                var color = "#999";
                $('search_box').style.color = color;
                $('search_box').value = text;
                DOM.addEventListener($('search_box'), "focus", function (evt) {
                    if ($('search_box').value == text) {
                        $('search_box').style.color = "";
                        $('search_box').value = "";
                    }
                });
                DOM.addEventListener($('search_box'), "blur", function (evt) {
                    if ($('search_box').value == "") {
                        $('search_box').style.color = color;
                        $('search_box').value = text;
                    }
                });
            }

            // add event listener to the search form
            DOM.addEventListener($('search_form'), "submit", function (evt) { self.filterThemes(evt, "search", $('search_box').value) });

            var filter_links = DOM.getElementsByClassName(document, "theme-nav-cat");

            // add event listeners to all of the category links
            filter_links.forEach(function (filter_link) {
                var evt_listener_added = 0;
                var getArgs = LiveJournal.parseGetArgs(filter_link.href);
                for (var arg in getArgs) {
                    if (!getArgs.hasOwnProperty(arg)) continue;
                    if (arg == "authas" || arg == "show") continue;
                    DOM.addEventListener(filter_link, "click", function (evt) { self.filterThemes(evt, arg, unescape( getArgs[arg] ) ) });
                    evt_listener_added = 1;
                    break;
                }

                // if there was no listener added to a link, add it without any args (for the 'featured' category)
                if (!evt_listener_added) {
                    DOM.addEventListener(filter_link, "click", function (evt) { self.filterThemes(evt, "", "") });
                }
            });
        },
        filterThemes: function (evt, key, value) {
            if (key == "show") {
                // need to go back to page 1 if the show amount was switched because
                // the current page may no longer have any themes to show on it
                Customize.page = 1;
            } else if (key != "page") {
                Customize.resetFilters();
            }

            // do not do anything with a layoutid of 0
            if (key == "layoutid" && value == 0) {
                Event.stop(evt);
                return;
            }

            if (key == "cat") Customize.cat = value;
            if (key == "layoutid") Customize.layoutid = value;
            if (key == "designer") Customize.designer = value;
            if (key == "search") Customize.search = value;
            if (key == "page") Customize.page = value;
            if (key == "show") Customize.show = value;

            this.updateContent({
                method: "GET",
                cat: Customize.cat,
                layoutid: Customize.layoutid,
                designer: Customize.designer,
                search: Customize.search,
                page: Customize.page,
                show: Customize.show,
                theme_chooser_id: $('theme_chooser_id').value
            });

            Event.stop(evt);

            if (key == "search") {
                $("search_btn").disabled = true;
            } else if (key == "page" || key == "show") {
                $("paging_msg_area_top").innerHTML = "<em>Please wait...</em>";
                $("paging_msg_area_bottom").innerHTML = "<em>Please wait...</em>";
            } else {
                Customize.cursorHourglass(evt);
            }
        },
        onData: function (data) {
            Customize.CurrentTheme.updateContent({
                show: Customize.show
            });
            Customize.hideHourglass();
        },
        onRefresh: function (data) {
            this.initWidget();
            Customize.ThemeChooser.initWidget();
        }
    ];
}

1;
