// Cassette.h: interface for the CCassette class.
//
//////////////////////////////////////////////////////////////////////

#pragma once

#include <array>
#include <vector>

#include "DllDefines.h"

constexpr auto MAX_SLOT_PER_CASSETTE = 25;

enum class eSLOT_STATE
{
    INVALID = -1,
    NO_WAFER,
    PRESENT,
    CROSS_SLOT,
    DOUBLE_WAFER,
    WAFER_PROCESSED,
    WAFER_PROCESSING,
    WAFER_REJECTED,
    MAX_SLOT_STATE,
    ALL_SLOTS_OK = NO_WAFER,
};

enum class eDIRECTION
{
    BOTTOM_UP,
    TOP_DOWN,
};

enum class ePROCESS_STATUS
{
    INVALID = -1,
    NO_WAFER_PRESENT,
    WAFER_PRESENT,
    WAFER_REJECT, // due to cannot pick wafer ???
};

enum class eCASSETTE
{
    CURRENT_CASSETTE = 0,
    NEW_CASSETTE     = 1,
};

using stCassette = struct _stCassette
{
    eCASSETTE cassState{ 0 };

    std::array<eSLOT_STATE, MAX_SLOT_PER_CASSETTE> arrSlotInfo;
};

class MCCTRDLLCLASS CCassette
{
public:
    CCassette();
    virtual ~CCassette();

    // methods
    bool               IsAllSlotsFilled();
    int                GetNextEmptyWaferSlot(eDIRECTION bDir = eDIRECTION::BOTTOM_UP);
    static eSLOT_STATE IsAnyCrossSlotorDoubleWafer(stCassette stCass, int nSlots);
    eSLOT_STATE        IsAnyCrossSlotOrDoubleWafer();
    bool               IsCassNeedProcessing();
    int                GetNextWaferSlot();
    bool               IsAllSlotsProcessed();
    stCassette         GetCassetteInfo() const;
    eSLOT_STATE        GetSlotStatus(int nSlotNo);

    bool Init(const stCassette& stCass, int nNoOfSlot = MAX_SLOT_PER_CASSETTE);

    bool   Init(int iNumOfSlot);
    bool   SetNumOfSlot(int iNumOfSlot);
    bool   SetSlotPitch(double dSlotPitch);
    bool   SetSlotStatus(int iSlotNum, eSLOT_STATE iSlotStatus);

    bool   SetCurSlotNum(int iSlotNum);
    bool   SetCurSlotStatus(ePROCESS_STATUS iSlotStatus);

    int    GetNumOfSlot() const;
    double GetSlotPitch() const;

    int    GetCurrentSlot() const;
    int    GetNextSlotNum() const;
    int    GetNextSlot();
    bool   IndexToNextSlot();
    void   ResetSlotNum();

private:
    // methods
    bool CheckValidStatus(eSLOT_STATE nStatus) const;
    bool CheckSlotNoValid(int nSlotNo) const;

    // attribute
    stCassette m_stCassette;
    // attributes
    std::vector<ePROCESS_STATUS> m_vecSlot;
    int                          m_iCurSlot{ 0 };

    double m_dSlotPitch{ 0.0 };
};
