/*
 * Copyright 2014 gitblit.com.
 *
 * 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 com.gitblit.wicket.pages;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.eclipse.jgit.lib.Repository;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.TicketModel;
import com.gitblit.models.TicketModel.Change;
import com.gitblit.models.TicketModel.Field;
import com.gitblit.models.TicketModel.Status;
import com.gitblit.models.UserModel;
import com.gitblit.tickets.TicketMilestone;
import com.gitblit.tickets.TicketNotifier;
import com.gitblit.tickets.TicketResponsible;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.MarkdownTextArea;
import com.gitblit.wicket.panels.TicketRelationEditorPanel;

/**
 * Page for creating a new ticket.
 *
 * @author James Moger
 *
 */
public class NewTicketPage extends RepositoryPage {

	private IModel<TicketModel.Type> typeModel;

	private IModel<String> titleModel;

	private MarkdownTextArea descriptionEditor;

	private IModel<String> topicModel;

	private IModel<String> mergeToModel;

	private IModel<TicketResponsible> responsibleModel;

	private IModel<TicketMilestone> milestoneModel;

	private Label descriptionPreview;

	private IModel<TicketModel.Priority> priorityModel;

	private IModel<TicketModel.Severity> severityModel;

	private IModel<List<String>> dependenciesModel;

	public NewTicketPage(PageParameters params) {
		super(params);

		UserModel currentUser = GitBlitWebSession.get().getUser();
		if (currentUser == null) {
			currentUser = UserModel.ANONYMOUS;
		}

		if (!currentUser.isAuthenticated || !app().tickets().isAcceptingNewTickets(getRepositoryModel())) {
			// tickets prohibited
			setResponsePage(TicketsPage.class, WicketUtils.newRepositoryParameter(repositoryName));
		}

		typeModel = Model.of(TicketModel.Type.defaultType);
		titleModel = Model.of();
		topicModel = Model.of();
		mergeToModel = Model.of(Repository.shortenRefName(getRepositoryModel().mergeTo));
		responsibleModel = Model.of();
		milestoneModel = Model.of();
		severityModel = Model.of(TicketModel.Severity.defaultSeverity);
		priorityModel = Model.of(TicketModel.Priority.defaultPriority);
		dependenciesModel = (IModel) Model.ofList(new ArrayList<String>());

		setStatelessHint(false);
		setOutputMarkupId(true);

		Form<Void> form = new Form<Void>("editForm");
		add(form);

		form.add(new DropDownChoice<TicketModel.Type>("type", typeModel, Arrays.asList(TicketModel.Type.choices())));
		form.add(new TextField<String>("title", titleModel));
		form.add(new TextField<String>("topic", topicModel));
		form.add(new DropDownChoice<TicketModel.Severity>("severity", severityModel, Arrays.asList(TicketModel.Severity.choices())));

		final IModel<String> markdownPreviewModel = Model.of();
		descriptionPreview = new Label("descriptionPreview", markdownPreviewModel);
		descriptionPreview.setEscapeModelStrings(false);
		descriptionPreview.setOutputMarkupId(true);
		form.add(descriptionPreview);

		descriptionEditor = new MarkdownTextArea("description", markdownPreviewModel, descriptionPreview);
		descriptionEditor.setRepository(repositoryName);
		form.add(descriptionEditor);
		
		form.add(new TicketRelationEditorPanel("dependencies", dependenciesModel,  null) {

			private static final long serialVersionUID = 1L;
			
			@Override
			protected RepositoryModel getRepositoryModel() {
				return NewTicketPage.this.getRepositoryModel();
			}
		});

		if (currentUser.canAdmin(null, getRepositoryModel())) {
			// responsible
			Set<String> userlist = new TreeSet<String>();

			if (UserModel.ANONYMOUS.canPush(getRepositoryModel())
					|| AuthorizationControl.AUTHENTICATED == getRepositoryModel().authorizationControl) {
				// 	authorization is ANONYMOUS or AUTHENTICATED (i.e. all users can be set responsible)
				userlist.addAll(app().users().getAllUsernames());
			} else {
				// authorization is by NAMED users (users with PUSH permission can be set responsible)
				for (RegistrantAccessPermission rp : app().repositories().getUserAccessPermissions(getRepositoryModel())) {
					if (rp.permission.atLeast(AccessPermission.PUSH)) {
						userlist.add(rp.registrant);
					}
				}
			}

			List<TicketResponsible> responsibles = new ArrayList<TicketResponsible>();
			for (String username : userlist) {
				UserModel user = app().users().getUserModel(username);
				if (user != null && !user.disabled) {
					TicketResponsible responsible = new TicketResponsible(user);
					responsibles.add(responsible);
				}
			}
			Collections.sort(responsibles);
			Fragment responsible = new Fragment("responsible", "responsibleFragment", this);
			responsible.add(new DropDownChoice<TicketResponsible>("responsible", responsibleModel, responsibles));
			form.add(responsible.setVisible(!responsibles.isEmpty()));

			// milestone
			List<TicketMilestone> milestones = app().tickets().getMilestones(getRepositoryModel(), Status.Open);
			Fragment milestone = new Fragment("milestone", "milestoneFragment", this);
			milestone.add(new DropDownChoice<TicketMilestone>("milestone", milestoneModel, milestones));
			form.add(milestone.setVisible(!milestones.isEmpty()));

			// priority
			Fragment priority = new Fragment("priority", "priorityFragment", this);
			priority.add(new DropDownChoice<TicketModel.Priority>("priority", priorityModel, Arrays.asList(TicketModel.Priority.choices())));
			form.add(priority);

			// integration branch
			List<String> branches = new ArrayList<String>();
			for (String branch : getRepositoryModel().getLocalBranches()) {
				// exclude ticket branches
				if (!branch.startsWith(Constants.R_TICKET)) {
					branches.add(Repository.shortenRefName(branch));
				}
			}
			branches.remove(Repository.shortenRefName(getRepositoryModel().HEAD));
			branches.add(0, Repository.shortenRefName(getRepositoryModel().HEAD));

			Fragment mergeto = new Fragment("mergeto", "mergeToFragment", this);
			mergeto.add(new DropDownChoice<String>("mergeto", mergeToModel, branches));
			form.add(mergeto.setVisible(!branches.isEmpty()));
		} else {
			// user does not have permission to assign milestone, responsible, or mergeto
			form.add(new Label("responsible").setVisible(false));
			form.add(new Label("milestone").setVisible(false));
			form.add(new Label("mergeto").setVisible(false));
			form.add(new Label("priority").setVisible(false));
		}

		form.add(new AjaxButton("create") {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
				String title = titleModel.getObject();
				if (StringUtils.isEmpty(title)) {
					return;
				}

				String createdBy = GitBlitWebSession.get().getUsername();
				Change change = new Change(createdBy);
				change.setField(Field.title, title);
				change.setField(Field.body, descriptionEditor.getText());
				String topic = topicModel.getObject();
				if (!StringUtils.isEmpty(topic)) {
					change.setField(Field.topic, topic);
				}

				// type
				TicketModel.Type type = TicketModel.Type.defaultType;
				if (typeModel.getObject() != null) {
					type = typeModel.getObject();
				}
				change.setField(Field.type, type);

				// responsible
				TicketResponsible responsible = responsibleModel == null ? null : responsibleModel.getObject();
				if (responsible != null) {
					change.setField(Field.responsible, responsible.username);
				}

				// milestone
				TicketMilestone milestone = milestoneModel == null ? null : milestoneModel.getObject();
				if (milestone != null) {
					change.setField(Field.milestone, milestone.name);
				}

				// severity
				TicketModel.Severity severity = TicketModel.Severity.defaultSeverity;
				if (severityModel.getObject() != null) {
					severity = severityModel.getObject();
				}
				change.setField(Field.severity, severity);

				// priority
				TicketModel.Priority priority = TicketModel.Priority.defaultPriority;
				if (priorityModel.getObject() != null) {
					priority = priorityModel.getObject();
				}
				change.setField(Field.priority, priority);

				// integration branch
				String mergeTo = mergeToModel.getObject();
				if (!StringUtils.isEmpty(mergeTo)) {
					change.setField(Field.mergeTo, mergeTo);
				}
				
				change.setDeltaField(Field.dependency, Collections.<String>emptyList(), dependenciesModel.getObject());

				TicketModel ticket = app().tickets().createTicket(getRepositoryModel(), 0L, change);
				if (ticket != null) {
					TicketNotifier notifier = app().tickets().createNotifier();
					notifier.sendMailing(ticket);

					redirectTo(TicketsPage.class, WicketUtils.newObjectParameter(getRepositoryModel().name, "" + ticket.number));
				} else {
					// TODO error
				}
			}
		});

		Button cancel = new Button("cancel") {
			private static final long serialVersionUID = 1L;

			@Override
			public void onSubmit() {
				setResponsePage(TicketsPage.class, getPageParameters());
			}
		};
		cancel.setDefaultFormProcessing(false);
		form.add(cancel);

	}

	@Override
	protected String getPageName() {
		return getString("gb.newTicket");
	}

	@Override
	protected Class<? extends BasePage> getRepoNavPageClass() {
		return TicketsPage.class;
	}
}
