#ifndef _JOURNAL_H_
#define _JOURNAL_H_

#include "control.h"
#include "fiscal.h"

#define EVENT_RECORDS_COUNT  150 // число записей в журнале

#pragma pack(push, 1)
/// структура записи журнала рабочих событий
typedef struct{
  // время создания записи
  CPU_INT32U time;
  
  // тип события
  CPU_INT08U event;
    #define JOURNAL_EVENT_NO_EVENT         0  // нет события
    #define JOURNAL_EVENT_MONEY_NOTE       1  // событие получения купюры
    #define JOURNAL_EVENT_MONEY_COIN       2  // событие получения монеты (кол-во рублей)
    #define JOURNAL_EVENT_START_SESSION    3  // событие начала сеанса
    #define JOURNAL_EVENT_END_SESSION      4  // событие конца сеанса
    #define JOURNAL_EVENT_DEVICE_ON        6  // включение устройства
    #define JOURNAL_EVENT_PRINT_BILL       7  // печать чека
    #define JOURNAL_EVENT_PRINT_Z          8  // печать z-отчета
    #define JOURNAL_EVENT_PRINT_X          9  // печать x-отчета
    #define JOURNAL_EVENT_PRINT_BUF        10  // печать x-отчета
    #define JOURNAL_EVENT_CHANGE_MODE      11  // смена режима
    #define JOURNAL_EVENT_INCASSATION      12  // инкассация 
    #define JOURNAL_EVENT_PASS_FAIL        13  // неверный ввод пароля
    #define JOURNAL_EVENT_EMAIL_OK         14  // правильно отправлен email
    #define JOURNAL_EVENT_EMAIL_FAIL       15  // ошибка при отправке email
    #define JOURNAL_EVENT_CARD_ACCEPTED    16  // принята карта, сумма безнала
    #define JOURNAL_EVENT_CARD_REJECTED    17  // карта отклонена
    #define JOURNAL_EVENT_POST_UNAVIABLE   18  // пост недоступен
  
    #define JOURNAL_EVENT_SOLARIUM_CLEANING_START    19   // начало уборки солярия
    #define JOURNAL_EVENT_SOLARIUM_CLEANING_END      20   // конец уборки солярия
    #define JOURNAL_EVENT_SOLARIUM_SERVICE_START     21   // начало сервиса солярия
    #define JOURNAL_EVENT_SOLARIUM_SERVICE_END       22   // конец сервиса солярия
    #define JOURNAL_EVENT_SOLARIUM_TESTMODE_START    23   // начало теста солярия
    #define JOURNAL_EVENT_SOLARIUM_TESTMODE_END      24   // конец теста солярия
  
    // ошибка связи с купюрником
    #define ERROR_VALIDATOR_CONN           25
    // критическая ошибка работы купюрника
    #define ERROR_VALIDATOR_FAILURE        26

    // некритические ошибки купюроприемника
    // Выброс купюры при замине
    #define ERROR_VALIDATOR_INSERTION       27
    // Выброс купюры по маг.датчику
    #define ERROR_VALIDATOR_MAGNETIC        28
    // Выброс купюры при транспортировке
    #define ERROR_VALIDATOR_CONVEYING       29
    // Выброс купюры по идентификации
    #define ERROR_VALIDATOR_IDENT           30
    // Выброс купюры по верификации 
    #define ERROR_VALIDATOR_VRFY            31
    // Выброс купюры по оптич.датчику 
    #define ERROR_VALIDATOR_OPT             32
    // Выброс купюры по запрету
    #define ERROR_VALIDATOR_INHIBIT         33
    // Выброс купюры по емкостному датчику
    #define ERROR_VALIDATOR_CAP             34
    // Выброс купюры по длине
    #define ERROR_VALIDATOR_LNG             35
    // Кассета заполнена
    #define ERROR_STACKER_FULL              36
    // Кассета отсутствует
    #define ERROR_STACKER_REMOVED           37
    // Замин в купюроприемнике
    #define ERROR_BV_JAMMED                 38
    // Замин в кассете
    #define ERROR_ST_JAMMED                 39
    // Попытка обмана
    #define ERROR_CHEATED                   40
    // Ошибка стекерного мотора
    #define ERROR_FLR_STACKER               41
    // Ошибка скорости транспорт.мотора
    #define ERROR_TR_SPEED                  42
    // Ошибка транспорт.мотора
    #define ERROR_FLR_TRANSPORT             43
    // Ошибка механизма выравнивания
    #define ERROR_FLR_ALIGNIN               44
    // Кассета отсутствует
    #define ERROR_FLR_INIT_CAS              45
    // Ошибка оптики
    #define ERROR_FLR_OPT                   46
    // Ошибка маг.датчика
    #define ERROR_FLR_MAG                   47
    // Ошибка емкостного датчика
    #define ERROR_FLR_CAP                   48
    // ошибка связи с модемом
    #define ERROR_MODEM_CONN                49
    // событие отправки журнала
    #define JOURNAL_EVENT_FTP_SEND          50
    // событие отмены чека
    #define JOURNAL_CANSEL_BILL             51
    // ошибка связи с фискальником
    #define ERROR_FR_CONN                   52

    #define JOURNAL_EVENT_ABONEMENT_ACCEPTED    53  // принят абонемент, сумма безнала
    #define JOURNAL_EVENT_ABONEMENT_REJECTED    54  // абонемент отклонен

    #define JOURNAL_EVENT_ABONEMENT_PAY_ACCEPTED    55  // куплен абонемент, сумма безнала
    #define JOURNAL_EVENT_ABONEMENT_PAY_REJECTED    56  // покупка абонемента отклонена

    #define JOURNAL_EVENT_ABONEMENT_BALANCE         57  // чтение баланса
    #define JOURNAL_EVENT_ABONEMENT_WRONG           58  // не верная карта

    #define JOURNAL_EVENT_CARD_ABONEMENT_ACCEPTED   59  // принята карта, сумма безнала - оплата абонемента

    #define JOURNAL_EVENT_CARD_ABONEMENT_REAPEATE   60  // превышено количество посещений в день

    // ВСЕ ОШИБКИ ФР ФАТАЛЬНЫЕ
    #define ERROR_FR                        61

    #define JOURNAL_EVENTS_COUNT             (ERROR_FR + FR_ERROR_NUMBER)  // число событий

  // канал
  union
  {
    CPU_INT08U channel;
    CPU_INT08U type_abonement;
  };

  /// @brief данные: для получения денег - номинал купюры, для сеанса - длительность оплаченного времени, мин., потраченные деньги
  union
  {
    CPU_INT16U data;
    CPU_INT16U money;
  };

  /// @brief Потраченные бонусы
  union
  {
    CPU_INT16U bonus;
  };

  /// @brief Дата окончания абонемента, пароль, сумма для банка в копейках
  union
  {
    CPU_INT32U time_before;
    CPU_INT32U password;
    CPU_INT32U money_bank;
  };

  /// @brief Номер карты
  union
  {
    CPU_INT32U number_abonement;
  };

  /// @brief Деньги на карте
  union
  {
    CPU_INT16U money_sum;
  };

  /// @brief Бонусы на карте
  union
  {
    CPU_INT16U bonus_sum;
  };

}TEventRecord;        // 22 байта
#pragma pack(pop)

#if defined(BOARD_SOLARIUM_VLAD)

/// структура записи счетчиков о солярии в одном режиме
typedef struct{
    /// сумма денег
    CPU_INT32U money;
    /// число запусков
    CPU_INT32U runs;
    /// количество секунд работы 
    CPU_INT32U worktime;

    // деньги с карт
    CPU_INT32U card_money;
    // бонуса с карт
    CPU_INT32U card_bonus;
}SolarCountersRecord;

/// структура записи счетчиков о солярии в одном режиме
typedef struct{
  /// число запусков
  CPU_INT32U runs;
  // деньги с карт
  CPU_INT32U card_money;
  // бонуса с карт
  CPU_INT32U card_bonus;
}AbonentCountersRecord;

/// структура всех счетчиков для солярия
typedef struct{
    /// счетчики по соляриям и режимам
    SolarCountersRecord solar_chm[CHANNELS_NUM * SOLAR_MODES_COUNT];
    /// счетчики теста по соляриям и режимам
    SolarCountersRecord solar_chm_test[CHANNELS_NUM * SOLAR_MODES_COUNT];
    /// счетчики по режимам
    SolarCountersRecord solar_m[SOLAR_MODES_COUNT];
    /// счетчики теста по режимам
    SolarCountersRecord solar_m_test[SOLAR_MODES_COUNT];

    /// счетчики по абонементам
    AbonentCountersRecord abonement[5];

    /// отработанное время коллатен+макси по соляриям
    CPU_INT32U collaten_time[CHANNELS_NUM];
    /// отработанное время ультрафиолет+макси по соляриям
    CPU_INT32U uf_time[CHANNELS_NUM];
    /// всего денег
    CPU_INT32U common_money;
    /// денег наличными
    CPU_INT32U cash_money;
    /// денег по карте
    CPU_INT32U card_money;
    /// денег по абонементам
    CPU_INT32U abonement_money;
    /// количество купюр
    CPU_INT32U bill_count;
    /// количество уборок
    CPU_INT32U cleaning_count[CHANNELS_NUM];
    /// суммарное время уборок
    CPU_INT32U cleaning_time[CHANNELS_NUM];
    /// средняя длительность уборки
    CPU_INT32U cleaning_mean_time[CHANNELS_NUM];
    /// тестов всего
    CPU_INT32U test_count[CHANNELS_NUM];
    /// наработка тестов всего
    CPU_INT32U test_time[CHANNELS_NUM];
    /// средняя длительность теста
    CPU_INT32U test_mean_time[CHANNELS_NUM];
    /// контрольная сумма
    CPU_INT16U checksum;
}SolarCounters;
    
#endif

// структура для хранения счетчиков
typedef struct{
  // число запусков поканально
  CPU_INT32U  CounterChannelRun[CHANNELS_NUM];
  // Суммарное время работы поканально, сек.
  CPU_INT32U  CounterChannelTime[CHANNELS_NUM];
  // Сумма денег поканально  
  CPU_INT32U  CounterChannelMoney[CHANNELS_NUM];
  // Сумма безнала поканально
  CPU_INT32U  CounterChannelCard[CHANNELS_NUM];
  // Сумма по абонементу
  CPU_INT32U  CounterChannelAbonement[CHANNELS_NUM];
  
  // общее число запусков 
  CPU_INT32U  CounterRun;
  // общее Суммарное время работы, сек.
  CPU_INT32U  CounterTime;
  // общее Сумма денег   
  CPU_INT32U  CounterMoney;
  // общее Сумма безнала
  CPU_INT32U  CounterCard;
  // общее Сумма по абонементу
  CPU_INT32U  CounterAbonement;

  // счетчики купюр в купюрнике по номиналам
  CPU_INT32U  CounterBillNominals[24];
  // общий счетчик купюр (всего в кассете)
  CPU_INT32U  BillsCount;
}TCounters;


// структура для хранения длинных счетчиков
typedef struct{
  // число запусков поканально
  CPU_INT32U  CounterChannelRunLong[CHANNELS_NUM];
  // Суммарное время работы поканально, сек.
  CPU_INT32U  CounterChannelTimeLong[CHANNELS_NUM];
  // Сумма денег поканально  
  CPU_INT32U  CounterChannelMoneyLong[CHANNELS_NUM];
  // Сумма безнала поканально
  CPU_INT32U  CounterChannelCardLong[CHANNELS_NUM];
  // Сумма по абонементу
  CPU_INT32U  CounterChannelAbonementLong[CHANNELS_NUM];
  
  CPU_INT32U  CounterRunLong;
  CPU_INT32U  CounterTimeLong;
  CPU_INT32U  CounterMoneyLong;
  CPU_INT32U  CounterCardLong;
  CPU_INT32U  CounterAbonementLong;

  CPU_INT16U  crc;
}TCountersLong;


extern void IncBillnomCounter(CPU_INT32U index);
extern void CheckLongCounters(void);
extern void SaveEventRecord(CPU_INT08U channel, CPU_INT08U event, CPU_INT16U data);

/// @brief Сохранение записи журнала
/// @param record запись журнала
extern void SaveEventAbonementRecord(TEventRecord * record);

extern void SetErrorFlag(CPU_INT08U error);
extern void ClrErrorFlag(CPU_INT08U error);
extern int TstErrorFlag(CPU_INT08U error);
extern int TstCriticalErrors(void);
extern void ClearEventJournal(void);
extern void GetEventStr(char* str, char event);
extern int GetEventRecord(TEventRecord* record, CPU_INT32U index);
extern void IncCounter(CPU_INT08U ch, CPU_INT32U time, CPU_INT32U money, CPU_INT08U card);
extern void ClearCounters(void);
extern void ErrorServer(void);
extern int TstCriticalValidatorErrors(void);
extern void ClrValidatorErrors(void);
extern void PrintEventJournalRecordEng(char* str, TEventRecord *record);
extern void GetEventStrEng(char* str, char event);
extern void ClearBillnomCounter(void);
extern void JournalInit(void);

#endif //#ifndef _JOURNAL_H_
