/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.openmeetings.cli;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;

public class OmHelpFormatter extends HelpFormatter {
	private static String GENERAL_OPTION_GROUP = "";
	private int maxPrefixLength = 0;
	
	@SuppressWarnings("unchecked")
	private List<OmOption> getReqOptions(Options opts) {
		//suppose we have only 1 group (for now)
		OptionGroup g = ((List<OptionGroup>)opts.getRequiredOptions()).get(0);
		List<OmOption> result = new ArrayList<OmOption>(g.getOptions());
		Collections.sort(result, new Comparator<OmOption>() {
			public int compare(OmOption o1, OmOption o2) {
				return o1.getOrder() - o2.getOrder();
			}
		});
		return result;
	}
	
	@SuppressWarnings("unchecked")
	private LinkedHashMap<String, List<OmOption>> getOptions(Options opts, int leftPad) {
		final String longOptSeparator = " ";
		final String lpad = createPadding(leftPad);
		final String lpadParam = createPadding(leftPad + 2);
		List<OmOption> reqOptions = getReqOptions(opts);
		LinkedHashMap<String, List<OmOption>> map = new LinkedHashMap<String, List<OmOption>>(reqOptions.size());
		map.put(GENERAL_OPTION_GROUP, new ArrayList<OmOption>());
		for (OmOption o : reqOptions) {
			map.put(o.getOpt(), new ArrayList<OmOption>());
		}
		for (OmOption o : (Collection<OmOption>)opts.getOptions()) {
			//TODO need better check (required option should go first and should not be duplicated
			boolean skipOption = map.containsKey(o.getOpt());
			boolean mainOption = skipOption || o.getGroup() == null;
			
			// first create list containing only <lpad>-a,--aaa where
			// -a is opt and --aaa is long opt; in parallel look for
			// the longest opt string this list will be then used to
			// sort options ascending
			StringBuilder optBuf = new StringBuilder();
			if (o.getOpt() == null) {
				optBuf.append(mainOption ? lpad : lpadParam).append("   ").append(getLongOptPrefix())
						.append(o.getLongOpt());
			} else {
				optBuf.append(mainOption ? lpad : lpadParam).append(getOptPrefix())
						.append(o.getOpt());

				if (o.hasLongOpt()) {
					optBuf.append(',').append(getLongOptPrefix())
							.append(o.getLongOpt());
				}
			}

			if (o.hasArg()) {
				String argName = o.getArgName();
				if (argName != null && argName.length() == 0) {
					// if the option has a blank argname
					optBuf.append(' ');
				} else {
					optBuf.append(o.hasLongOpt() ? longOptSeparator : " ");
					optBuf.append("<")
							.append(argName != null ? o.getArgName()
									: getArgName()).append(">");
				}
			}

			o.setHelpPrefix(optBuf);
			maxPrefixLength = Math.max(optBuf.length(), maxPrefixLength);
			
			if (skipOption) {
				//TODO need better check (required option should go first and should not be duplicated
				continue;
			}
			String grp = o.getGroup();
			grp = grp == null ? GENERAL_OPTION_GROUP : grp;
			String[] grps = grp.split(",");
			for(String g : grps) {
				map.get(g).add(o);
			}
		}
		for (String _key : map.keySet()) {
			final String key = _key;
			List<OmOption> options = map.get(key);
			Collections.sort(options, new Comparator<OmOption>(){
				public int compare(OmOption o1, OmOption o2) {
					boolean o1opt = !o1.isOptional(key);
					boolean o2opt = !o2.isOptional(key);
					return (o1opt && o2opt || !o1opt && !o2opt) ? (o1.getOpt() == null ? 1 : -1) : (o1opt ? -1 : 1);
				}
				
			});
			if (opts.hasOption(key)) {
				options.add(0, (OmOption)opts.getOption(key));
			}
		}
		return map;
	}
	
	private StringBuilder getReqOptionsString(Options opts) {
		String delim = "";
		StringBuilder result = new StringBuilder();
		for (Option o : getReqOptions(opts)) {
			result.append(delim).append("-").append(o.getOpt());
			delim = "|";
		}
		return result;
	}
	
	@Override
	protected StringBuffer renderOptions(StringBuffer sb, int width, Options options, int leftPad, int descPad) {
		final String dpad = createPadding(descPad);
		final String optional = "(optional) ";

		LinkedHashMap<String, List<OmOption>> optList = getOptions(options, leftPad);

		char[] delimiter = new char[width - 2];
		Arrays.fill(delimiter, '-');

		for (String key : optList.keySet()) {
			if (GENERAL_OPTION_GROUP.equals(key)) {
				sb.append("General options:").append(getNewLine());
			}
			for (OmOption option : optList.get(key)) {
				StringBuilder optBuf = new StringBuilder(option.getHelpPrefix());

				if (optBuf.length() < maxPrefixLength) {
					optBuf.append(createPadding(maxPrefixLength - optBuf.length()));
				}

				optBuf.append(dpad);

				int nextLineTabStop = maxPrefixLength + descPad;

				if (option.isOptional(key)) {
					optBuf.append(optional);
				}
				if (option.getDescription() != null) {
					optBuf.append(option.getDescription());
				}

				renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());

				sb.append(getNewLine());
			}
			sb.append(delimiter).append(getNewLine());
		}
		return sb;
	}

	@Override
	public void printHelp(PrintWriter pw, int width, String cmdLineSyntax,
			String header, Options options, int leftPad, int descPad,
			String footer, boolean autoUsage) {
		if ((cmdLineSyntax == null) || (cmdLineSyntax.length() == 0)) {
			throw new IllegalArgumentException("cmdLineSyntax not provided");
		}

		printUsage(pw, width, cmdLineSyntax, options);

		if ((header != null) && (header.trim().length() > 0)) {
			printWrapped(pw, width, header);
		}

		printOptions(pw, width, options, leftPad, descPad);

		if ((footer != null) && (footer.trim().length() > 0)) {
			printWrapped(pw, width, footer);
		}
	}
    
	public void printUsage(PrintWriter pw, int width, String app, Options opts) {
		pw.println(String.format("usage: %1$s [%2$s] [options]", app, getReqOptionsString(opts)));
	}
}
