/*
 *   Copyright (c) 2022 Project CHIP Authors
 *   All rights reserved.
 *
 *   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.matter.controller.commands.common;

import chip.devicecontroller.ChipDeviceController;
import com.matter.controller.config.PersistentStorage;
import com.matter.controller.config.PersistentStorageOpCertStore;
import com.matter.controller.config.PersistentStorageOperationalKeystore;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

public abstract class MatterCommand extends Command {
  private final ChipDeviceController mChipDeviceController;
  private final PersistentStorage mDefaultStorage = new PersistentStorage();
  private final PersistentStorage mCommissionerStorage = new PersistentStorage();
  private final PersistentStorageOperationalKeystore mOperationalKeystore =
      new PersistentStorageOperationalKeystore();
  private final PersistentStorageOpCertStore mOpCertStore = new PersistentStorageOpCertStore();

  private final Optional<CredentialsIssuer> mCredIssuerCmds;
  private final StringBuffer mCommissionerName = new StringBuffer();
  private final StringBuffer mPaaTrustStorePath = new StringBuffer();
  private final StringBuffer mCDTrustStorePath = new StringBuffer();
  private final AtomicLong mCommissionerNodeId = new AtomicLong();
  private final AtomicBoolean mUseMaxSizedCerts = new AtomicBoolean();;
  private final AtomicBoolean mOnlyAllowTrustedCdKeys = new AtomicBoolean();;
  private Optional<String> mTestResult = Optional.empty();

  public MatterCommand(
      ChipDeviceController controller, String commandName, CredentialsIssuer credIssuerCmds) {
    this(controller, commandName, credIssuerCmds, null);
  }

  public MatterCommand(
      ChipDeviceController controller,
      String commandName,
      CredentialsIssuer credIssuerCmds,
      String helpText) {
    super(commandName, helpText);
    this.mCredIssuerCmds = Optional.ofNullable(credIssuerCmds);
    this.mChipDeviceController = controller;

    addArgument(
        "--paa-trust-store-path",
        mPaaTrustStorePath,
        "Path to directory holding PAA certificate information.  Can be absolute or relative to the current working "
            + "directory.",
        true);
    addArgument(
        "--cd-trust-store-path",
        mCDTrustStorePath,
        "Path to directory holding CD certificate information.  Can be absolute or relative to the current working "
            + "directory.",
        true);
    addArgument(
        "--commissioner-name",
        mCommissionerName,
        "Name of fabric to use. Valid values are \"alpha\", \"beta\", \"gamma\", and integers greater than or equal to "
            + "4.  The default if not specified is \"alpha\".",
        true);
    addArgument(
        "--commissioner-nodeid",
        0,
        Long.MAX_VALUE,
        mCommissionerNodeId,
        "The node id to use for chip-tool.  If not provided, kTestControllerNodeId (112233, 0x1B669) will be used.",
        true);
    addArgument(
        "--use-max-sized-certs",
        mUseMaxSizedCerts,
        "Maximize the size of operational certificates. If not provided or 0 (\"false\"), normally sized operational "
            + "certificates are generated.",
        true);
    addArgument(
        "--only-allow-trusted-cd-keys",
        mOnlyAllowTrustedCdKeys,
        "Only allow trusted CD verifying keys (disallow test keys). If not provided or 0 (\"false\"), untrusted CD "
            + "verifying keys are allowed. If 1 (\"true\"), test keys are disallowed.",
        true);
  }

  // This method returns the commissioner instance to be used for running the command.
  public ChipDeviceController currentCommissioner() {
    return mChipDeviceController;
  }

  /////////// Command Interface /////////
  @Override
  public void run() throws Exception {
    // TODO: setup chip storage from Java, currently it is using example one from chip-tool
    // maybeSetUpStack();
    runCommand();
    // maybeTearDownStack();
  }

  protected abstract void runCommand();

  private void maybeSetUpStack() throws Exception {
    mDefaultStorage.init();
    mOperationalKeystore.init(mDefaultStorage);
    mOpCertStore.init(mDefaultStorage);
  }

  private void maybeTearDownStack() {
    // ToDo:We need to call DeviceController::Shutdown()
  }

  public void setTestResult(String result) {
    mTestResult = Optional.of(result);
  }

  public void expectSuccess(long timeout) {
    expectResult("Success", timeout);
  }

  private void expectResult(String expectedResult, long timeout) {
    long start = System.currentTimeMillis();
    while (!mTestResult.isPresent())
      try {
        if (System.currentTimeMillis() > (start + timeout)) {
          throw new RuntimeException("timeout!");
        }
        Thread.sleep(100);
      } catch (InterruptedException ex) {
      }

    if (!mTestResult.isPresent()) {
      throw new RuntimeException("received empty test result");
    }

    if (!mTestResult.get().equals(expectedResult)) {
      if (!expectedResult.equals("Success")) {
        System.out.format(
            "%s command failed:%n    Expected: %s%n    Got: %s%n",
            getName(), expectedResult, mTestResult);
        throw new RuntimeException(getName());
      } else {
        System.out.format("%s command failed: %s%n", getName(), mTestResult.get());
      }
    }
    mTestResult = Optional.empty();
  }
}
