/*
 * Copyright (c) 2021 OBiBa. All rights reserved.
 *
 * This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.obiba.opal.shell.commands.options;

import java.io.Console;
import java.util.ArrayList;
import java.util.List;

import org.obiba.opal.shell.OpalShell;

/**
 * Interacts with the user at the {@link Console} command line to build a list of attributes needed to construct a
 * {@link Certificate}.
 */
public class CertificateInfo {

  private final static String DEFAULT_VALUE = "Unknown";

  private final OpalShell shell;

  private final List<Attribute> infoList;

  public CertificateInfo(OpalShell shell) {
    this.shell = shell;
    infoList = new ArrayList<>();
    infoList.add(new Attribute("CN", DEFAULT_VALUE, "What is your first and last name?"));
    infoList.add(new Attribute("OU", DEFAULT_VALUE, "What is the name of your organizational unit?"));
    infoList.add(new Attribute("O", DEFAULT_VALUE, "What is the name of your organization?"));
    infoList.add(new Attribute("L", DEFAULT_VALUE, "What is the name of your City or Locality?"));
    infoList.add(new Attribute("ST", DEFAULT_VALUE, "What is the name of your State or Province?"));
    infoList.add(new Attribute("C", DEFAULT_VALUE, "What is the two-letter country code for this unit?"));
  }

  private String getConfirmationQuestion() {
    return "Is " + getDnString() + " correct?";
  }

  private String getDnString() {
    StringBuilder sb = new StringBuilder();
    for(Attribute attribute : infoList) {
      sb.append(attribute.getName()).append("=").append(attribute.getValue()).append(", ");
    }
    sb.setLength(sb.length() - 2);
    return sb.toString();
  }

  private String getConfirmationPrompt(String answer) {
    return "  [" + answer + "]:  ";
  }

  /**
   * Builds Certificate attributes interactively with user.
   *
   * @return the attributes as a String (e.g. CN=Administrator, OU=Bioinformatics, O=GQ, L=Montreal, ST=Quebec, C=CA)
   */
  public String getCertificateInfoAsString() {
    do {
      getCertificateInfoAttributes();
    } while(!isCertificateCorrect());
    return getDnString();
  }

  private void getCertificateInfoAttributes() {
    shell.printf("%s:\n", "Certificate creation");
    for(Attribute attribute : infoList) {
      shell.printf(" %s\n", attribute.getQuestion());
      attribute.setValue(shell.prompt(attribute.getPrompt()));
    }
  }

  private boolean isCertificateCorrect() {
    shell.printf(" %s\n", getConfirmationQuestion());
    String ans;
    boolean helpUser = false;
    do {
      if(helpUser) shell.printf(" Please respond with one of the following: 'yes', 'y', 'no', 'n'. Case is ignored.\n");
      helpUser = true;
      ans = "no";
      String answer = shell.prompt(getConfirmationPrompt(ans));
      if(answer != null && !"".equals(answer)) {
        ans = answer;
      }
    } while(!("yes".equalsIgnoreCase(ans) || "no".equalsIgnoreCase(ans) || "y".equalsIgnoreCase(ans) ||
        "n".equalsIgnoreCase(ans)));
    return "yes".equalsIgnoreCase(ans) || "y".equalsIgnoreCase(ans);
  }

  public static class Attribute {

    private final String name;

    private String value;

    private final String question;

    public Attribute(String name, String value, String question) {
      this.name = name;
      this.value = value;
      this.question = question;
    }

    public String getQuestion() {
      return question;
    }

    public String getValue() {
      return value;
    }

    public String getName() {
      return name;
    }

    public void setValue(String value) {
      if(value != null && !"".equals(value)) {
        this.value = value;
      }
    }

    public String getPrompt() {
      return "  [" + value + "]:  ";
    }

  }
}
