/*
 * 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.Arrays;
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.Owner;
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;

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);

					// 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);

					// save the owner change
					List<Owner> owners = Arrays.asList((Owner) GitBlitWebSession.get().getUser());
					app().gitblit().setOwners(repositoryModel, owners);

					// 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();
			PersonIdent author = new PersonIdent(user.getDisplayName(), user.emailAddress);

			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.release();
			}
		} catch (UnsupportedEncodingException e) {
			logger().error(null, e);
		} catch (IOException e) {
			logger().error(null, e);
		} finally {
			odi.release();
			db.close();
		}
		return success;
	}
}
