/*
 * 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.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.wicket.behavior.SimpleAttributeModifier;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

import com.gitblit.Constants;
import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.Constants.AuthorizationControl;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.FileUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.AccessPolicyPanel;
import com.gitblit.wicket.panels.BooleanChoiceOption;
import com.gitblit.wicket.panels.BooleanOption;
import com.gitblit.wicket.panels.RepositoryNamePanel;
import com.google.common.base.Optional;

public class NewRepositoryPage extends RootSubPage {

	private final RepositoryModel repositoryModel;
	private IModel<Boolean> addReadmeModel;
	private Model<String> gitignoreModel;
	private IModel<Boolean> addGitflowModel;
	private IModel<Boolean> addGitignoreModel;
	private AccessPolicyPanel accessPolicyPanel;
	private RepositoryNamePanel namePanel;

	public NewRepositoryPage() {
		// create constructor
		super();
		repositoryModel = new RepositoryModel();

		setupPage(getString("gb.newRepository"), "");

		setStatelessHint(false);
		setOutputMarkupId(true);
	}

	@Override
	protected boolean requiresPageMap() {
		return true;
	}

	@Override
	protected Class<? extends BasePage> getRootNavPageClass() {
		return RepositoriesPage.class;
	}

	@Override
	protected void onInitialize() {
		super.onInitialize();

		CompoundPropertyModel<RepositoryModel> rModel = new CompoundPropertyModel<>(repositoryModel);
		Form<RepositoryModel> form = new Form<RepositoryModel>("editForm", rModel) {

			private static final long serialVersionUID = 1L;

			@Override
			protected void onSubmit() {
				try {
					if (!namePanel.updateModel(repositoryModel)) {
						return;
					}
					accessPolicyPanel.updateModel(repositoryModel);

					repositoryModel.owners = new ArrayList<String>();
					repositoryModel.owners.add(GitBlitWebSession.get().getUsername());

					// setup branch defaults
					boolean useGitFlow = addGitflowModel.getObject();

					repositoryModel.HEAD = Constants.R_MASTER;
					repositoryModel.mergeTo = Constants.MASTER;
					if (useGitFlow) {
						// tickets normally merge to develop unless they are hotfixes
						repositoryModel.mergeTo = Constants.DEVELOP;
					}

					repositoryModel.allowForks = app().settings().getBoolean(Keys.web.allowForking, true);

					// optionally generate an initial commit
					boolean addReadme = addReadmeModel.getObject();
					String gitignore = null;
					boolean addGitignore = addGitignoreModel.getObject();
					if (addGitignore) {
						gitignore = gitignoreModel.getObject();
						if (StringUtils.isEmpty(gitignore)) {
							throw new GitBlitException(getString("gb.pleaseSelectGitIgnore"));
						}
					}

					// init the repository
					app().gitblit().updateRepositoryModel(repositoryModel.name, repositoryModel, true);

					// optionally create an initial commit
					initialCommit(repositoryModel, addReadme, gitignore, useGitFlow);

				} catch (GitBlitException e) {
					error(e.getMessage());
					return;
				}
				setRedirect(true);
				setResponsePage(SummaryPage.class, WicketUtils.newRepositoryParameter(repositoryModel.name));
			}
		};

		// do not let the browser pre-populate these fields
		form.add(new SimpleAttributeModifier("autocomplete", "off"));

		namePanel = new RepositoryNamePanel("namePanel", repositoryModel);
		form.add(namePanel);

		// prepare the default access controls
		AccessRestrictionType defaultRestriction = AccessRestrictionType.fromName(
				app().settings().getString(Keys.git.defaultAccessRestriction, AccessRestrictionType.PUSH.name()));
		if (AccessRestrictionType.NONE == defaultRestriction) {
			defaultRestriction = AccessRestrictionType.PUSH;
		}
		AuthorizationControl defaultControl = AuthorizationControl.fromName(
				app().settings().getString(Keys.git.defaultAuthorizationControl, AuthorizationControl.NAMED.name()));

		if (AuthorizationControl.AUTHENTICATED == defaultControl) {
			defaultRestriction = AccessRestrictionType.PUSH;
		}

		repositoryModel.authorizationControl = defaultControl;
		repositoryModel.accessRestriction = defaultRestriction;

		accessPolicyPanel = new AccessPolicyPanel("accessPolicyPanel", repositoryModel);
		form.add(accessPolicyPanel);

		//
		// initial commit options
		//

		// add README
		addReadmeModel = Model.of(false);
		form.add(new BooleanOption("addReadme",
				getString("gb.initWithReadme"),
				getString("gb.initWithReadmeDescription"),
				addReadmeModel));

		// add .gitignore
		File gitignoreDir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
		File [] files = gitignoreDir.listFiles();
		if (files == null) {
			files = new File[0];
		}
		List<String> gitignores = new ArrayList<String>();
		for (File file : files) {
			if (file.isFile() && file.getName().endsWith(".gitignore")) {
				gitignores.add(StringUtils.stripFileExtension(file.getName()));
			}
		}
		Collections.sort(gitignores);

		gitignoreModel = Model.of("");
		addGitignoreModel = Model.of(false);
		form.add(new BooleanChoiceOption<String>("addGitIgnore",
				getString("gb.initWithGitignore"),
				getString("gb.initWithGitignoreDescription"),
				addGitignoreModel,
				gitignoreModel,
				gitignores).setVisible(gitignores.size() > 0));

		// TODO consider gitflow at creation (ticket-55)
		addGitflowModel = Model.of(false);
		form.add(new BooleanOption("addGitFlow",
				"Include a .gitflow file",
				"This will generate a config file which guides Git clients in setting up Gitflow branches.",
				addGitflowModel).setVisible(false));

		form.add(new Button("create"));

		add(form);
	}

	/**
	 * Prepare the initial commit for the repository.
	 *
	 * @param repository
	 * @param addReadme
	 * @param gitignore
	 * @param addGitFlow
	 * @return true if an initial commit was created
	 */
	protected boolean initialCommit(RepositoryModel repository, boolean addReadme, String gitignore,
			boolean addGitFlow) {
		boolean initialCommit = addReadme || !StringUtils.isEmpty(gitignore) || addGitFlow;
		if (!initialCommit) {
			return false;
		}

		// build an initial commit
		boolean success = false;
		Repository db = app().repositories().getRepository(repositoryModel.name);
		ObjectInserter odi = db.newObjectInserter();
		try {

			UserModel user = GitBlitWebSession.get().getUser();
			String email = Optional.fromNullable(user.emailAddress).or(user.username + "@" + "gitblit");
			PersonIdent author = new PersonIdent(user.getDisplayName(), email);

			DirCache newIndex = DirCache.newInCore();
			DirCacheBuilder indexBuilder = newIndex.builder();

			if (addReadme) {
				// insert a README
				String title = StringUtils.stripDotGit(StringUtils.getLastPathElement(repositoryModel.name));
				String description = repositoryModel.description == null ? "" : repositoryModel.description;
				String readme = String.format("## %s\n\n%s\n\n", title, description);
				byte [] bytes = readme.getBytes(Constants.ENCODING);

				DirCacheEntry entry = new DirCacheEntry("README.md");
				entry.setLength(bytes.length);
				entry.setLastModified(System.currentTimeMillis());
				entry.setFileMode(FileMode.REGULAR_FILE);
				entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));

				indexBuilder.add(entry);
			}

			if (!StringUtils.isEmpty(gitignore)) {
				// insert a .gitignore file
				File dir = app().runtime().getFileOrFolder(Keys.git.gitignoreFolder, "${baseFolder}/gitignore");
				File file = new File(dir, gitignore + ".gitignore");
				if (file.exists() && file.length() > 0) {
					byte [] bytes = FileUtils.readContent(file);
					if (!ArrayUtils.isEmpty(bytes)) {
						DirCacheEntry entry = new DirCacheEntry(".gitignore");
						entry.setLength(bytes.length);
						entry.setLastModified(System.currentTimeMillis());
						entry.setFileMode(FileMode.REGULAR_FILE);
						entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));

						indexBuilder.add(entry);
					}
				}
			}

			if (addGitFlow) {
				// insert a .gitflow file
				Config config = new Config();
				config.setString("gitflow", null, "masterBranch", Constants.MASTER);
				config.setString("gitflow", null, "developBranch", Constants.DEVELOP);
				config.setString("gitflow", null, "featureBranchPrefix", "feature/");
				config.setString("gitflow", null, "releaseBranchPrefix", "release/");
				config.setString("gitflow", null, "hotfixBranchPrefix", "hotfix/");
				config.setString("gitflow", null, "supportBranchPrefix", "support/");
				config.setString("gitflow", null, "versionTagPrefix", "");

				byte [] bytes = config.toText().getBytes(Constants.ENCODING);

				DirCacheEntry entry = new DirCacheEntry(".gitflow");
				entry.setLength(bytes.length);
				entry.setLastModified(System.currentTimeMillis());
				entry.setFileMode(FileMode.REGULAR_FILE);
				entry.setObjectId(odi.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, bytes));

				indexBuilder.add(entry);
			}

			indexBuilder.finish();

			if (newIndex.getEntryCount() == 0) {
				// nothing to commit
				return false;
			}

			ObjectId treeId = newIndex.writeTree(odi);

			// Create a commit object
			CommitBuilder commit = new CommitBuilder();
			commit.setAuthor(author);
			commit.setCommitter(author);
			commit.setEncoding(Constants.ENCODING);
			commit.setMessage("Initial commit");
			commit.setTreeId(treeId);

			// Insert the commit into the repository
			ObjectId commitId = odi.insert(commit);
			odi.flush();

			// set the branch refs
			RevWalk revWalk = new RevWalk(db);
			try {
				// set the master branch
				RevCommit revCommit = revWalk.parseCommit(commitId);
				RefUpdate masterRef = db.updateRef(Constants.R_MASTER);
				masterRef.setNewObjectId(commitId);
				masterRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
				Result masterRC = masterRef.update();
				switch (masterRC) {
				case NEW:
					success = true;
					break;
				default:
					success = false;
				}

				if (addGitFlow) {
					// set the develop branch for git-flow
					RefUpdate developRef = db.updateRef(Constants.R_DEVELOP);
					developRef.setNewObjectId(commitId);
					developRef.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
					Result developRC = developRef.update();
					switch (developRC) {
					case NEW:
						success = true;
						break;
					default:
						success = false;
					}
				}
			} finally {
				revWalk.close();
			}
		} catch (UnsupportedEncodingException e) {
			logger().error(null, e);
		} catch (IOException e) {
			logger().error(null, e);
		} finally {
			odi.close();
			db.close();
		}
		return success;
	}
}
