/*
 * Copyright 2012 s_wolff.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.aegee.runanddine;

import java.text.SimpleDateFormat;
import java.util.List;

import org.aegee.runanddine.advertisement.AdvertisementMailEditor;
import org.aegee.runanddine.feedback.FeedbackInspector;
import org.aegee.runanddine.feedback.GracefulMailOfThanksMailEditor;
import org.aegee.runanddine.information.InformationMailEditor;
import org.aegee.runanddine.pathfinder.DistanceMatrixPage;
import org.aegee.runanddine.pathfinder.MainCourseSelector;
import org.aegee.runanddine.pathfinder.OptGroup;
import org.aegee.runanddine.pathfinder.assignmentbuilding.GroupsAndAssignmentEditor;
import org.aegee.runanddine.pathfinder.assignmentbuilding.OptimizationOverviewPage;
import org.aegee.runanddine.pathfinder.groupbuilding.GroupBuilderOverviewPage;
import org.aegee.runanddine.pathfinder.groupbuilding.GroupManager;
import org.aegee.runanddine.registration.GroupRegistration;
import org.aegee.runanddine.registration.ParticipantManager;
import org.aegee.runanddine.registration.SingleRegistration;
import org.aegee.runanddine.registrationvalidation.RegistrationValidationMailEditor;
import org.aegee.runanddine.runanddine.RunAndDine;
import org.aegee.runanddine.runanddine.RunAndDineComparator;
import org.aegee.runanddine.runanddine.RunAndDineEditor;
import org.aegee.runanddine.status.RunAndDineStatus;
import org.aegee.runanddine.status.RunAndDineStatusManager;
import org.aegee.runanddine.util.data.ModelNotExistingException;
import org.apache.wicket.Page;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.request.mapper.parameter.PageParameters;

/**
 * Overview page for backend
 */
public class OverviewPage extends BasePage {

    /**
     * Date formatter
     */
    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yy");
    
    /**
     * Default no status label
     */
    private static final String DEFAULT_NO_STATUS_LABEL = "[pending]";

    /**
     * Page constructor
     * @param parameters HTTP parameters 
     */
    public OverviewPage(PageParameters parameters) {
        super(parameters);

        List<RunAndDine> list = RunAndDine.OBJECTS.getAllShown();
        RunAndDineComparator.sortInverted(list);

        ListView<RunAndDine> listView = new ListView<RunAndDine>("repeater", list) {

            @Override
            protected void populateItem(ListItem<RunAndDine> item) {
                RunAndDine event = item.getModelObject();
                item.add(new Label("runAndDineDate", DATE_FORMAT.format(event.getDate())));
                // 1: RunAndDineManager
                item.add(createLink("linkInit", new RunAndDineEditor(event)));
                // 2: Advertisement
                item.add(createLink("linkAd", new AdvertisementMailEditor(event)));
                item.add(new Label("statusAd", getStatus(event.getId(), AdvertisementMailEditor.class)));
                // 3: Registrations
                item.add(createLink("linkReg", new ParticipantManager(event)));
                int singleRegs = SingleRegistration.OBJECTS.getAllByRunAndDineId(event.getId()).size();
                int groupRegs = GroupRegistration.OBJECTS.getAllByRunAndDineId(event.getId()).size();
                String display = String.format("%s Single Registrations<br>%s Group Registrations", singleRegs, groupRegs);
                item.add(new Label("statusReg", display).setEscapeModelStrings(false));
                // 4: Validation mail
                item.add(createLink("linkValMail", new RegistrationValidationMailEditor(event)));
                item.add(new Label("statusVal", getStatus(event.getId(), RegistrationValidationMailEditor.class)));
                // 5: Validations
                item.add(createLink("linkVal", new ParticipantManager(event)));
                int singleVals = SingleRegistration.OBJECTS.getAllValidatedByRunAndDineId(event.getId()).size();
                int groupVals = GroupRegistration.OBJECTS.getAllValidatedByRunAndDineId(event.getId()).size();
                display = String.format("%s Single Validations<br>%s Group Validations", singleVals, groupVals);
                item.add(new Label("statusValNum", display).setEscapeModelStrings(false));
                // 6: Group Proposal
                item.add(createLink("linkGroupProposal", new GroupBuilderOverviewPage(event)));
                item.add(new Label("statusGroupProp", getStatus(event.getId(), GroupBuilderOverviewPage.class)));
                // 7: Group Editor
                item.add(createLink("linkGroup", new GroupManager(event)));
                int numOptGroups = OptGroup.OBJECTS.getAllByRunAndDineId(event.getId()).size();
                display = String.format("%s Groups built", numOptGroups);
                item.add(new Label("statusNumGroups", display).setEscapeModelStrings(false));
                // 8: MainCourseSelector
                item.add(createLink("linkMainCourse", new MainCourseSelector(event)));
                item.add(new Label("statusMainCourse", getStatus(event.getId(), MainCourseSelector.class)));
                // 9: Distance Matrix
                item.add(createLink("linkDM", new DistanceMatrixPage(event)));
                item.add(new Label("statusDM", getStatus(event.getId(), DistanceMatrixPage.class)));
                // 10: Assignment Proposal
                item.add(createLink("linkOpt", new OptimizationOverviewPage(event)));
                item.add(new Label("statusAssiProp", getStatus(event.getId(), OptimizationOverviewPage.class)));
                // 11: Assignment Editor
                item.add(createLink("linkGAE", new GroupsAndAssignmentEditor(event)));
                // 12: Information Mail
                item.add(createLink("linkInfo", new InformationMailEditor(event)));
                item.add(new Label("statusInfo", getStatus(event.getId(), InformationMailEditor.class)));
                //13: GracefulMailOfThanks
                item.add(new BookmarkablePageLink("linkGraceMail", GracefulMailOfThanksMailEditor.class, new PageParameters("id=" + new Integer(event.getId()))));
                item.add(new Label("statusGrace", getStatus(event.getId(), GracefulMailOfThanksMailEditor.class)));
                // 14.Feedback inspector
                item.add(createLink("linkFeedback", new FeedbackInspector(event)));
            }
        };

        this.add(listView);
    }

    /**
     * Create link
     * @param id HTML identifier
     * @param page Target page
     * @return Link object
     */
    private static Link createLink(String id, final Page page) {
        return new Link(id) {

            @Override
            public void onClick() {
                this.setResponsePage(page);
            }
        };
    }

    /**
     * Get status for step identified by class
     * @param runAndDineId ID of RunAndDine
     * @param clz Class of corresponding step
     * @return Status
     */
    private static String getStatus(int runAndDineId, Class<?> clz) {
        String status = DEFAULT_NO_STATUS_LABEL;
        try {
            RunAndDineStatus stat = RunAndDineStatusManager.getInstance().getById(runAndDineId);
            String query = stat.getStatusInformation(clz.getName());
            if (query != null && !query.trim().equals("")) {
                status = query;
            }
        } catch (ModelNotExistingException e) {
            RunAndDineStatus stat = new RunAndDineStatus(runAndDineId);
            RunAndDineStatusManager.getInstance().save(stat);
        }
        return status;
    }
}
