/*
 * Copyright (C) 2022 MediaTek Inc.
 *
 * 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.
 */
#ifndef INCLUDE_MTKCAM_INTERFACES_UTILS_SCENARIORECORDER_ISCENARIORECORDER_H_
#define INCLUDE_MTKCAM_INTERFACES_UTILS_SCENARIORECORDER_ISCENARIORECORDER_H_

#include <mtkcam-interfaces/utils/ScenarioRecorder/ScenarioRecorderDef.h>
#include <mtkcam-interfaces/utils/metadata/IMetadata.h>

#include <memory>
#include <string>

namespace NSCam {
namespace TuningUtils {
namespace scenariorecorder {

class ScenarioRecorderInitializerImpl;

class ScenarioRecorderInitializer {
 public:
  // Can be only used by sevice main()
  ScenarioRecorderInitializer();
  ~ScenarioRecorderInitializer();

 private:
  std::unique_ptr<ScenarioRecorderInitializerImpl> mImpl;
};

/**
 * @brief IScenarioRecorder is a log service. Compare to
 * ulog service, it makes log organized in a fixed format.
 * Users provide information by paramerters and the strings
 * which they want to print. Scenario recorder would help to
 * print. Log files would be separated by capture and preview.
 * Both types of files follow NDD file name policy. This log
 * system record tuning interest in log files. The candidates
 * of users are tuning related modules.
 */
class IScenarioRecorder {
 public:
  /**
   * @brief Tell scenario recorder NddInformation. So that it
   *        could handle Ndd debug task by itself.
   *
   * @param uniqueKey          - Device unique key.
   * @param reqNo              - Pipeline request number.
   * @param frameNo            - Pipeline frame number.
   * @param isCapture          - Is capture or not.
   */
  virtual void recordNddInfo(int32_t uniqueKey, int32_t reqNo,
      int32_t frameNo, bool isCapture) = 0;

  /**
   * @brief Check if scenario recorder is enable or not.
   *
   * @return true Scenario recorder is enable.
   * @return false Scenario recorder is off.
   */
  virtual bool isScenarioRecorderOn() = 0;

  /**
   * @brief Submit decision record to ScenarioRecorder to record log string.
   *        reasonString size should be less than 1024
   * @param pHalMeta       - HalMetadata.
   * @param param          - Decision parameters.
   * @param reasonString   - Reason string which user want to present.
   */
  virtual void submitDecisionRecord(const IMetadata* pHalMeta,
                                    const DecisionInput& param,
                                    const char* reasonString) = 0;
  /**
   * @brief Submit decision record to ScenarioRecorder to record log string.
   *        reasonString size should be less than 1024
   * @param nddKey         - NDD key generated by NDDUtils.
   * @param param          - Decision parameters.
   * @param reasonString   - Reason string which user want to present.
   */
  virtual void submitDecisionRecord(const int64_t nddKey,
                                    const DecisionInput& param,
                                    const char* reasonString) = 0;
  /**
   * @brief Submit execution record to ScenarioRecorder to record log string.
   *        resultString size should be less than 1024
   * @param pHalMeta       - HalMetadata.
   * @param param          - Execution result parameters.
   * @param resultString   - Result string which user want to present.
   */
  virtual void submitExecutionRecord(const IMetadata* pHalMeta,
                                     const ExecResultInput& param,
                                     const char* resultString) = 0;
  /**
   * @brief Submit execution record to ScenarioRecorder to record log string.
   *        resultString size should be less than 1024
   * @param nddKey         - NDD key generated by NDDUtils.
   * @param param          - Execution result parameters.
   * @param resultString   - Result string which user want to present.
   */
  virtual void submitExecutionRecord(const int64_t nddKey,
                                     const ExecResultInput& param,
                                     const char* resultString) = 0;

 public:
  /**
   *  ScenarioRecorder is a singleton pattern.
   *  User can get reference of ScenarioRecorder by "getInstance".
   *  @return             - Returns ScenarioRecorder&
   */
  static IScenarioRecorder* getInstance();
  virtual ~IScenarioRecorder() {}
};  // class ScenarioRecorder

}  // namespace scenariorecorder
}  // namespace TuningUtils
}  // namespace NSCam

#define WRITE_DECISION_LOG_INTO_FILE(_key, _decisionParam, _fmt, _args...)    \
  do {                                                                        \
    char _buffer[1024];                                                       \
    size_t _contentLen = ::snprintf(_buffer, sizeof(_buffer), _fmt, ##_args); \
    if (_contentLen > 0) {                                                    \
      using NSCam::TuningUtils::scenariorecorder::IScenarioRecorder;          \
      auto rc = IScenarioRecorder::getInstance();                             \
      if (rc)                                                                 \
          rc->submitDecisionRecord(_key, _decisionParam, _buffer);            \
    }                                                                         \
  } while (0)

#define WRITE_EXECUTION_LOG_INTO_FILE(_key, _resultParam, _fmt, _args...)   \
do {                                                                        \
  char _buffer[1024];                                                       \
  size_t _contentLen = ::snprintf(_buffer, sizeof(_buffer), _fmt, ##_args); \
  if (_contentLen > 0) {                                                    \
    using NSCam::TuningUtils::scenariorecorder::IScenarioRecorder;          \
    auto rc = IScenarioRecorder::getInstance();                             \
    if (rc)                                                                 \
        rc->submitExecutionRecord(_key, _resultParam, _buffer);             \
  }                                                                         \
} while (0)

#endif  // INCLUDE_MTKCAM_INTERFACES_UTILS_SCENARIORECORDER_ISCENARIORECORDER_H_
