/*
 * Copyright (c) 2009, Takeyuki Nagao
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the
 * following conditions are met:
 * 
 *  * Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

package jp.sourceforge.dvibrowser.dvicore.util;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jp.sourceforge.dvibrowser.dvicore.DviException;


// TODO: Find out what the purpose of this class is.
public class DviInfoDumper
{
  private final Config conf;

  public DviInfoDumper(Config conf)
  {
    this.conf = conf;
  }

  public void execute()
  throws DviException
  {
    try {
      System.out.printf("mode=%s\n", this.conf.mode);
      for (String a : this.conf.plainArgs) {
        System.out.printf("arg: %s\n", a);
      }
//    } catch (DviException ex) {
//      throw ex;
    } catch (Exception ex) {
      throw new DviException(ex);
    }
  }

  public static class ArgumentList
  extends LinkedList<String>
  {
	private static final long serialVersionUID = -9222800531977990881L;

	public ArgumentList(String [] args)
    {
      for (String a : args) add(a);
    }

    public String next()
    {
      if (size() == 0) return null;

      return removeFirst();
    }
  }

  @SuppressWarnings("unused")
  public static class Option
  {
    private final String longOpt;
    private final String shortOpt;
    private final int numArgs;
	private final String var;
    private final String description;

    public Option(String longOpt, String shortOpt,
      String var, String description)
    {
      this.longOpt = longOpt;
      this.shortOpt = shortOpt;
      this.var = var;
      this.numArgs = (var != null) ? 1 : 0;
      this.description = description;
    }
  }
  
  public static class Config
  {
    private String mode = "help";
    private ArrayList<String> plainArgs
      = new ArrayList<String>();

    private static Option [] options = {
      new Option("--help", "-h", null,     "Show this help"),
      new Option("--mode", "-m", "mode", "Set mode to <mode>")
    };

    public Config()
    {
    }

    public void setMode(String mode)
    {
      this.mode = mode.toLowerCase();
    }

    public void addPlainArgument(String a)
    {
      plainArgs.add(a);
    }

    private static final Pattern patShortOption
      = Pattern.compile("^(-[0-9a-zA-Z])(.*)$");
    private static final Pattern patLongOption
      = Pattern.compile("^(--[a-zA-Z][a-zA-Z0-9]*)(=(.*))?$");

    public static Config parseCommandLine(String [] args)
    throws DviException
    {
      ArgumentList al = new ArgumentList(args);
      Config conf = new Config();
      String a;
      while (null != (a = al.next())) {
        if (a.startsWith("-")) {
          Matcher mat;
          boolean handled = false;

          if ((mat = patLongOption.matcher(a)).find()) {
            String a2 = mat.group(1);
            String v = mat.group(3);
            System.out.println("found long option: " + a2 + "=>" + v);
            for (Option opt : options) {
              if (a2.equals(opt.longOpt)) {
                handled = true;
                if (opt.numArgs > 0) {
                  if (v == null)
                    throw new DviException
                      ("no value for option `" + a2 + "'");
                } else {
                  if (v != null)
                    throw new DviException
                      ("option `" + a2 + "' does not take argument");
                }
                break;
              }
            }
          } else if ((mat = patShortOption.matcher(a)).find()) {
            String a2 = mat.group(1);
            String v = mat.group(3);
            System.out.println("found short option: " + a2 + "=>" + v);
            for (Option opt : options) {
              if (a.equals(opt.shortOpt)) {
                handled = true;
                break;
              }
            }
          }

          if (!handled) {
            throw new DviException
              ("unrecognized option: " + a);
          }
        } else {
          conf.addPlainArgument(a);
        }
      }
      return conf;
    }
  }
}
