/**
 * @file       	AXMIspAe.hpp
 * @brief      	AEシーケンサ
 *
 * @par			言語
 *              C++
 */

#ifndef AXMISPAEA_HPP_
#define AXMISPAEA_HPP_

#include "AXMISPtype.hpp"
#include "AXMIspAeAlgorithm.hpp"
#include "AXMIspAeSetting.hpp"
#include "AXMCommon/AXMCommonStruct.hpp"
#include "AXMCommon/AXMCommonParam.hpp"

/**
 * @enum         ControlGroup
 * @brief        AEシーケンサ全処理IDグループ化用列挙型
 *
 * @n			
 */
#define EGROUPSHIFT 8
#define EGROUPMASK  0x0000FF00L
enum ControlGroup {
  E_CONGRP_COMMON    = (1 << EGROUPSHIFT) ,	// 共通部
  E_CONGRP_WEIGHT    = (2 << EGROUPSHIFT) ,	// OPD重み付け
  E_CONGRP_MANUAL    = (3 << EGROUPSHIFT) ,	// Manual mode
  E_CONGRP_MAINOBJ   = (4 << EGROUPSHIFT) ,	// 主要被写体
  E_CONGRP_HIST      = (5 << EGROUPSHIFT) ,	// ヒストグラム
#ifdef WDR
  E_CONGRP_WDR_EXRAT = (6 << EGROUPSHIFT) ,	// 露光比率指定WDR
  E_CONGRP_WDR_AUTO  = (7 << EGROUPSHIFT) ,	// Auto WDR
#endif
};

/**
 * @enum         ControlValue
 * @brief        AEシーケンサ全処理ID宣言用列挙型
 *
 * @n			
 */
enum ControlValue {
  E_WeightOPD			= (E_CONGRP_WEIGHT | 1),		// 1) OPD重み付け 
  E_CalcAverageOPD ,									// 2) OPD平均計算

  E_CalcAeDiff			= (E_CONGRP_COMMON | 1),		// 3) 偏差計算
  E_CalcAeDiffExtend	,								// 4) 偏差計算(拡張)
  E_CalcAeControlValue  ,								// 5) AE制御量計算
  E_SelectControlObject ,								// 6) 制御対象選択
  E_DecideControlValue ,								// 7) 制御量決定
  E_CalcLuminanceValue ,								// 8) 明るさ計算
  E_CalcISPGain ,										// 9) ISPゲイン計算
  E_ManageRoughIrisValue = (E_CONGRP_MANUAL | 1),		// 10)概略アイリス値管理

  E_CalcHistogram		= (E_CONGRP_HIST | 1),			// 11)
  E_DivHistogram,										// 12)
  E_CalcAverageLowLumiAreaOPD,							// 13)
  E_CalcAverageHighLumiAreaOPD,							// 14)
  E_CalcAverageALLHist,									// 15)

  E_CalcAverageMainObjectOPD = (E_CONGRP_MAINOBJ | 1),	// 16)
  E_CalcAverageNonMainObjectOPD,						// 17)
  E_WeightNonMainObjectArea,							// 18)
  E_CalcAverageALL,										// 19)

#ifdef WDR
  E_CalcWDRShortExposureTime = (E_CONGRP_WDR_EXRAT | 1),// 20)
  E_DecideWDRShortControlValue,							// 21)
  E_DecideWDRLongControlValue,							// 22)

  E_SetAutoWDRShortTarget = (E_CONGRP_WDR_AUTO | 1),	// 23)
  E_SetAutoWDRLongTarget,								// 24)
  E_CalcAutoWDRShortAverage,							// 25)
  E_CalcAutoWDRLongAverage,								// 26)
  E_DecideAutoWDRShortControlValue,						// 27)
  E_DecideAutoWDRLongControlValue,						// 28)
#endif
  E_TERMINATE	= 0xffffU				// 演算終了
};
/**
 * @var          E_CalcAverageALL
 * @brief        AEシーケンサ処理終了ID定数
 *
 * @n			   AEシーケンサ処理の終了を指定するID
 */
const int E_CONTROL_MAX = E_CalcAverageALL + 1;

/**
 * @class        AXMIspAeExecCalcBase
 * @brief        AEシーケンサ基本クラス
 *
 * @n		       AEの各モードで共通の処理を実行する
 */
class AXMIspAeExecCalcBase {
 public:
//	AXFLog m_log;

  const UCHAR *opdData;
  AXMIspAeControlExposure controlExposure;
  AXMIspAeSetting *objAeSettingRef;
  AXMIspAeBase *base;
  AXMispAeWeightOPD *weight;
  AXMIspAeAutoBLFLCHistogram *hist;
  AXMIspAeHistogramBase *histBase;
  AXMIspAEAutoBLFLCMainObject *mainObj;
#ifdef WDR
  AXMIspAeExposureRatioWDRMode *exprat;
  AXMIspAeAutoWDR *autoWdr;
#endif
  AXMIspAeModes AeModeSave2;

#ifdef PARASOFT_CPPTEST

  AXMispAeWeightOPD wobj;
  AXMIspAeAutoBLFLCHistogram hobj;
  AXMIspAEAutoBLFLCMainObject mobj;
#endif

#ifdef AE_DEBUG2
	int aeNum;
	int aePracIdx;
#endif
  ST_FROM_AE_TO_ISP execFromAeToIsp;		// 明るさ情報等送信用

 private:	//コピーコンストラクタをpublicからprivateに移動
  AXMIspAeExecCalcBase(AXMIspAeExecCalcBase &obj);
  AXMIspAeExecCalcBase& operator=(const AXMIspAeExecCalcBase& obj);        // =演算子オーバーロード

 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeExecCalcBase();

  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeExecCalcBase();

  /**
   * @brief      AE設定通知
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]   obj  設定情報
   */
  void notifyAeSequencer(AXMIspAeSetting *obj);
  /**
   * @brief      AEシーケンサ実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    contrl	シーケンス記述テーブル
   */
  void exec(const ControlValue contrl[]);

 private:
  /**
   * @brief      AeModeの変更をチェックする
   *
   * @n          複雑さ回避のために細分化
   */
  void checkModeChange(void);
  /**
   * @brief      インスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   * @param      [in]    AeMode              AEモード
   */
  void generateInstance(AXMIspAeSetting * objAeSettingRef , AXMIspAeModes AeMode);
  /**
   * @brief      OPD重み付けインスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   */
  void generateInstanceWeight(AXMIspAeSetting *objAeSettingRef);
  /**
   * @brief      自動補正インスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   */
  void generateInstanceMainObj(AXMIspAeSetting *objAeSettingRef);
  /**
   * @brief       ヒストグラム補正インスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   */
  void generateInstanceHist(AXMIspAeSetting *objAeSettingRef);
#ifdef WDR
  /**
   * @brief       露光比率指定WDRインスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   */
  void generateInstanceExposureRatio(AXMIspAeSetting *objAeSettingRef);
  /**
   * @brief      AutoWDRインスタンス生成
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    objAeSettingRef AE設定テーブルへのポインタ
   */
  void generateInstanceAutoWdr(AXMIspAeSetting *objAeSettingRef);
#endif
  /**
   * @brief      AEシーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]    contrl		シーケンス設定テーブル
   */
  void execSequence(const ControlValue contrl[]);
  /**
   * @brief       重み付けシーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceWeightGroup(const ControlValue contVal);
  /**
   * @brief      AE共通シーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceCommonGroup(const ControlValue contVal);
  /**
   * @brief      AEマニュアルモードシーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceManualGroup(const ControlValue contVal);
  /**
   * @brief      ヒストグラム補正シーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceHistGroup(const ControlValue contVal);
  /**
   * @brief      主要被写体補正シーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceMainObjGroup(const ControlValue contVal);
#ifdef WDR
  /**
   * @brief      露光比指定WDRシーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceExpRatGroup(const ControlValue contVal);
  /**
   * @brief      AutoWDRシーケンス実行
   *
   * @n          複雑さ回避のために細分化
   * @param      [in]  contVal		シーケンス設定テーブル
   */
  void execSequenceAutoWDRGroup(const ControlValue contVal);
#endif
  /**
   * @brief      OPD重み付け関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callWeightOPD(void);
  /**
   * @brief      OPD平均計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageOPD(void);

  /**
   * @brief      偏差計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAeDiff(void);
  /**
   * @brief      偏差計算関数呼出2
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAeDiffExtend(void);
  /**
   * @brief      AE制御量計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAeControlValue(void);
  /**
   * @brief      AE制御対象選択関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callSelectControlObject(void);
  /**
   * @brief      AE制御量決定関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callDecideControlValue(void);
  /**
   * @brief      明るさ計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcLuminanceValue(void);
  /**
   * @brief      ISPゲイン計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcISPGain(void);
  /**
   * @brief      概略アイリス値管理関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callManageRoughIrisValue(void);

  /**
   * @brief      ヒストグラム計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcHistogram(void);
  /**
   * @brief      ヒストグラム分割処理関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callDivHistogram(void);
  /**
   * @brief      低輝度エリアOPD平均関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageLowLumiAreaOPD(void);
  /**
   * @brief      高輝度エリアOPD平均関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageHighLumiAreaOPD(void);
  /**
   * @brief      全体平均計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageALLHist(void);

  /**
   * @brief      主要被写体エリアOPD平均関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageMainObjectOPD(void);
  /**
   * @brief      非主要被写体エリアOPD平均関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageNonMainObjectOPD(void);
  /**
   * @brief      非主要被写体重み付け関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callWeightNonMainObjectArea(void);
  /**
   * @brief      全体平均計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcAverageALL(void);
#ifdef WDR
  /**
   * @brief      WDR短時間露光計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callCalcWDRShortExposureTime(void);
  /**
   * @brief      WDR短時間露光決定関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callDecideWDRShortControlValue(void);
  /**
   * @brief      WDR長時間露光計算関数呼出
   *
   * @n          複雑さ回避のために細分化
   */
  void callDecideWDRLongControlValue(void);

  /**
   * @brief      AutoWDR短時間露光目標値設定
   *
   * @n
   */
  void callSetAutoWDRShortTarget(void);
  /**
   * @brief      AutoWDR長時間露光目標値設定
   *
   * @n
   */
  void callSetAutoWDRLongTarget(void);
  /**
   * @brief      AutoWDR短時間露光計算関数呼出
   *
   * @n
   */
  void callCalcAutoWDRShortAverage(void);
  /**
   * @brief      AutoWDR長時間露光計算関数呼出
   *
   * @n
   */
  void callCalcAutoWDRLongAverage(void);
  /**
   * @brief      AutoWDR短時間露光決定関数呼出
   *
   * @n
   */
  void callDecideAutoWDRShortControlValue(void);
  /**
   * @brief      AutoWDR長時間露光決定関数呼出
   *
   * @n
   */
  void callDecideAutoWDRLongControlValue(void);
#endif	
  /**
   * @brief      ダミー関数呼出
   *
   * @n			複雑さ回避のために細分化
   */
  void callNop(void);


//  void wait(void);
#ifdef PARASOFT_CPPTEST
  bool flag_newWeightStub;
  /**
   * @brief		C++テスト用スタブ関数 new
   *
   * @n
   */
  AXMispAeWeightOPD *newWeightStub(void);
  bool flag_newMainObjStub;
  /**
   * @brief		C++テスト用スタブ関数 new
   *
   * @n
   */
  AXMIspAEAutoBLFLCMainObject *newMainObjStub(void);
  bool flag_newHistStub;
  /**
   * @brief		C++テスト用スタブ関数 new
   *
   * @n
   */
  AXMIspAeAutoBLFLCHistogram *newHistStub(void);
  bool flag_newExpRatStub;
  /**
   * @brief		C++テスト用スタブ関数 new
   *
   * @n
   */
  AXMIspAeExposureRatioWDRMode *newExpRatStub(void);
  bool flag_newAutoWdrStub;
  /**
   * @brief		C++テスト用スタブ関数 new
   *
   * @n
   */
  AXMIspAeAutoWDR *newAutoWdrStub(void);
#endif

};

/**
 * @var    AXMIspAeManualModeControl
 * @brief  AEシーケンサ マニュアルモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeManualModeControl[E_CONTROL_MAX] = {
	E_WeightOPD,               // OPD重み付け
    E_CalcAverageOPD,			// OPD平均計算
		E_ManageRoughIrisValue,    // 概略アイリス値管理　※今回Irisは存在しないが、ゲインとシャッタースピードを送信する様に暫定で有効としておく
	  E_CalcLuminanceValue ,								// 7) 明るさ計算
    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAeUsualProgModeControl
 * @brief  AEシーケンサ 通常プログラムAEモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeUsualProgModeControl[E_CONTROL_MAX] = {
	E_WeightOPD,               // OPD重み付け
    E_CalcAverageOPD,          // OPD平均計算
    E_CalcAeDiff,              // 偏差計算
    E_CalcAeControlValue,      // AE制御量計算
    E_SelectControlObject,     // 制御対象選択
    E_DecideControlValue,      // 制御量決定
    E_CalcLuminanceValue,      // 明るさ計算
    E_CalcISPGain,             // ISPゲイン計算
    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };


/**
 * @var    AXMIspAeShutterControlModeControl
 * @brief  AEシーケンサ 通常シャッター制御AEモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeShutterControlModeControl[E_CONTROL_MAX] = {
    E_WeightOPD,					// OPD重み付け
    E_CalcAverageOPD,			// OPD平均計算
    E_CalcAeDiff,              // 偏差計算
    E_CalcAeControlValue,      // AE制御量計算
    E_SelectControlObject,     // 制御対象選択
    E_DecideControlValue,      // 制御量決定
    E_CalcLuminanceValue,      // 明るさ計算
    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAeShutterAndGainControlModeControl
 * @brief  AEシーケンサ 通常シャッター＆ゲイン制御AEモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeShutterAndGainControlModeControl[E_CONTROL_MAX] = {
    E_WeightOPD,					// OPD重み付け
    E_CalcAverageOPD,			// OPD平均計算
    E_CalcAeDiff,              // 偏差計算
    E_CalcAeControlValue,      // AE制御量計算
    E_SelectControlObject,     // 制御対象選択
    E_DecideControlValue,      // 制御量決定
    E_CalcLuminanceValue,      // 明るさ計算
    E_CalcISPGain,             // ISPゲイン計算
    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAeAutoBLFLCHistogramModeControl
 * @brief  AEシーケンサ 自動補正 ヒストグラム分割モード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeAutoBLFLCHistogramModeControl[E_CONTROL_MAX] = {
    E_CalcHistogram, 
	E_DivHistogram, 
	E_CalcAverageLowLumiAreaOPD,
    E_CalcAverageHighLumiAreaOPD, 
    E_CalcAverageALLHist,

    E_CalcAeDiff,              // 偏差計算 
    E_CalcAeControlValue,      // AE制御量計算
    E_SelectControlObject,     // 制御対象選択
    E_DecideControlValue,      // 制御量決定
    E_CalcLuminanceValue,      // 明るさ計算
    E_CalcISPGain,             // ISPゲイン計算

    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAEAutoBLFLCMainObjectModeControl
 * @brief  AEシーケンサ 自動補正 主要被写体指定モード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAEAutoBLFLCMainObjectModeControl[E_CONTROL_MAX] = {
    E_CalcAverageMainObjectOPD, 
	E_CalcAverageNonMainObjectOPD,
    E_WeightNonMainObjectArea, 
	E_CalcAverageALL,

    E_CalcAeDiff,              // 偏差計算
    E_CalcAeControlValue,      // AE制御量計算
    E_SelectControlObject,     // 制御対象選択
    E_DecideControlValue,      // 制御量決定
    E_CalcLuminanceValue,      // 明るさ計算
    E_CalcISPGain,             // ISPゲイン計算

    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAeExposureRatioWDRModeControl_Short
 * @brief  AEシーケンサ 露光比指定WDRモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeExposureRatioWDRModeControl_Short[E_CONTROL_MAX] = {
    E_WeightOPD,               // OPD重み付け    -+
    E_CalcAverageOPD,          // OPD平均計算     |←アイリス制御のために長時間露光時も行う
    E_CalcAeDiff,              // 偏差計算        |
	E_CalcAeControlValue,      // AE制御量計算   -+

#ifdef WDR
    E_DecideWDRLongControlValue,
#endif
    E_CalcLuminanceValue,      // 明るさ計算

	static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

const ControlValue AXMIspAeExposureRatioWDRModeControl_Long[E_CONTROL_MAX] = {
	E_WeightOPD,               // OPD重み付け
    E_CalcAverageOPD,          // OPD平均計算
	E_CalcAeDiffExtend,        // 偏差計算(拡張) 

#ifdef WDR
    E_DecideWDRShortControlValue,
#endif
	E_CalcLuminanceValue,      // 明るさ計算

	E_CalcISPGain,             // ISPゲイン計算

	static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @var    AXMIspAeAutoWDRControl_Short
 * @brief  AEシーケンサ オートWDRモード処理テーブル
 *
 * @n
 */
const ControlValue AXMIspAeAutoWDRControl_Short[E_CONTROL_MAX] = {
#ifdef WDR
	E_SetAutoWDRShortTarget,
#endif
    E_CalcHistogram, 
	E_DivHistogram, 
	E_CalcAverageLowLumiAreaOPD,
    E_CalcAverageHighLumiAreaOPD, 
#ifdef WDR
	E_CalcAutoWDRShortAverage,
#endif
    E_CalcAeDiff,              // 偏差計算 
    E_CalcAeControlValue,      // AE制御量計算
#ifdef WDR
	E_DecideAutoWDRShortControlValue,
#endif
    E_CalcLuminanceValue,      // 明るさ計算

	E_CalcISPGain,             // ISPゲイン計算

    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

const ControlValue AXMIspAeAutoWDRControl_Long[E_CONTROL_MAX] = {
#ifdef WDR
	E_SetAutoWDRLongTarget,
	E_CalcAutoWDRLongAverage,
#endif	
	E_CalcAeDiffExtend,        // 偏差計算(拡張) 
    E_CalcAeControlValue,      // AE制御量計算
#ifdef WDR
	E_DecideAutoWDRLongControlValue,
#endif
    E_CalcLuminanceValue,      // 明るさ計算

	E_CalcISPGain,             // ISPゲイン計算

    static_cast<ControlValue>(E_TERMINATE)					// 演算終了
    };

/**
 * @class AXMIspAeSequencer
 * @brief AEシーケンサ クラス
 *
 * @n			
 */
class AXMIspAeSequencer : public AXMIspAeExecCalcBase {
 private:
 public:
  /**
   * @brief  オブジェクトを初期化する
   *
   * @n
   */
  AXMIspAeSequencer();
  /**
   * @brief  オブジェクトを開放する
   *
   * @n
   */
  virtual ~AXMIspAeSequencer();
  /**
   * @brief		AEシーケンサ
   *
   * @n			AEシーケンサ実行
   * @param [in]    p_msg  メッセージ
   */
  void doCalc(ST_MSG *p_msg);

  /**
   * @brief		AEシーケンサダミー関数
   *
   * @n
   */
  void doCalcDummy();
};

#endif /* AXMISPAEA_HPP_ */

