//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop

#include <FMX.Platform.Win.hpp>
//#include <Winapi.Windows.hpp>
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "FCamera"
#pragma link "Winsoft.FireMonkey.ObrP.lib"
#pragma resource "*.fmx"
TFormMain *FormMain;
//---------------------------------------------------------------------------
__fastcall TFormMain::TFormMain(TComponent* Owner)
  : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::SetDevices()
{
  ComboBoxCamera->Items->BeginUpdate();
  try
  {
    String CurrentDeviceName = "";
    if (ComboBoxCamera->Selected != NULL)
      CurrentDeviceName = ComboBoxCamera->Selected->Text;

    TFVideoCaptureDevices Devices = FCamera->Devices;
    ComboBoxCamera->Items->Clear();
    for (int I = 0; I < Devices.Length; ++I)
      ComboBoxCamera->Items->Add(Devices[I].Name);

    int Index = ComboBoxCamera->Items->IndexOf(CurrentDeviceName);
    if (Index != -1)
      ComboBoxCamera->ItemIndex = Index;
  }
  __finally
  {
    ComboBoxCamera->Items->EndUpdate();
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::SetFormats()
{
  ComboBoxFormat->Items->BeginUpdate();
  try
  {
    ButtonSaveCurrentImage->Enabled = false;
    Timer->Enabled = false;
    FCamera->Active = false;
    TimerObr->Enabled = false;
    FObr->Active = false;
    if (ComboBoxCamera->Selected != NULL)
      FCamera->DeviceName = ComboBoxCamera->Selected->Text;
    else
      FCamera->DeviceName = "";
    ComboBoxFormat->Items->Clear();
    ComboBoxFormat->Enabled = FCamera->DeviceName.Length() > 0;
    if (ComboBoxFormat->Enabled)
    {
      TFCameraFormats Formats = FCamera->SupportedFormats;
      for (int I = 0; I < Formats.Length; ++I)
        if (Formats[I].AvgTimePerFrame == 0)
          ComboBoxFormat->Items->Add(IntToStr(Formats[I].Width) + "x" + IntToStr(Formats[I].Height) + " " + IntToStr(Formats[I].BitsPerPixel) + "bpp");
        else
          ComboBoxFormat->Items->Add(IntToStr(Formats[I].Width) + "x" + IntToStr(Formats[I].Height) + " " + IntToStr(10000000 / Formats[I].AvgTimePerFrame) + "Hz " + IntToStr(Formats[I].BitsPerPixel) + "bpp");
    }
  }
  __finally
  {
    ComboBoxFormat->Items->EndUpdate();
  }
}
//---------------------------------------------------------------------------
void __fastcall InitTrackBar(TLabel *TrackbarLabel, TTrackBar *TrackBar, TCheckBox *CheckBoxAuto)
{
  TrackbarLabel->Enabled = false;
  TrackBar->Enabled = false;
  CheckBoxAuto->Enabled = false;
}
//---------------------------------------------------------------------------
void __fastcall SetTrackBar(TLabel *TrackbarLabel, TTrackBar * TrackBar, TCheckBox *CheckBoxAuto, int Position, TFRange Range, bool Auto)
{
  CheckBoxAuto->IsChecked = Auto;
  TrackBar->Min = Range.Min;
  TrackBar->Max = Range.Max;
  TrackBar->Frequency = Range.Delta;

  TrackBar->Value = Position;

  TrackbarLabel->Enabled = true;
  CheckBoxAuto->Enabled = Range.Auto && Range.Manual;
  TrackBar->Enabled = !CheckBoxAuto->IsChecked;
}
//---------------------------------------------------------------------------
bool TrackBarsSetting = false;

void __fastcall TFormMain::SetTrackBars()
{
  if (!TrackBarsSetting)
  try
  {
    TrackBarsSetting = true;
    InitTrackBar(LabelBacklightCompensation, TrackBarBacklightCompensation, CheckBoxBacklightCompensation);
    InitTrackBar(LabelBrightness, TrackBarBrightness, CheckBoxBrightness);
    InitTrackBar(LabelColorEnable, TrackBarColorEnable, CheckBoxColorEnable);
    InitTrackBar(LabelContrast, TrackBarContrast, CheckBoxContrast);
    InitTrackBar(LabelExposure, TrackBarExposure, CheckBoxExposure);
    InitTrackBar(LabelFocus, TrackBarFocus, CheckBoxFocus);
    InitTrackBar(LabelGain, TrackBarGain, CheckBoxGain);
    InitTrackBar(LabelGamma, TrackBarGamma, CheckBoxGamma);
    InitTrackBar(LabelHue, TrackBarHue, CheckBoxHue);
    InitTrackBar(LabelIris, TrackBarIris, CheckBoxIris);
    InitTrackBar(LabelPan, TrackBarPan, CheckBoxPan);
    InitTrackBar(LabelRoll, TrackBarRoll, CheckBoxRoll);
    InitTrackBar(LabelSaturation, TrackBarSaturation, CheckBoxSaturation);
    InitTrackBar(LabelSharpness, TrackBarSharpness, CheckBoxSharpness);
    InitTrackBar(LabelTilt, TrackBarTilt, CheckBoxTilt);
    InitTrackBar(LabelWhiteBalance, TrackBarWhiteBalance, CheckBoxWhiteBalance);
    InitTrackBar(LabelZoom, TrackBarZoom, CheckBoxZoom);

    if (FCamera->DeviceName.Length() > 0)
    {
      if (FCamera->BacklightCompensationSupported)
        SetTrackBar(LabelBacklightCompensation, TrackBarBacklightCompensation, CheckBoxBacklightCompensation, FCamera->BacklightCompensation, FCamera->BacklightCompensationRange, FCamera->BacklightCompensationAuto);

      if (FCamera->BrightnessSupported)
        SetTrackBar(LabelBrightness, TrackBarBrightness, CheckBoxBrightness, FCamera->Brightness, FCamera->BrightnessRange, FCamera->BrightnessAuto);

      if (FCamera->ColorEnableSupported)
        SetTrackBar(LabelColorEnable, TrackBarColorEnable, CheckBoxColorEnable, FCamera->ColorEnable, FCamera->ColorEnableRange, FCamera->ColorEnableAuto);

      if (FCamera->ContrastSupported)
        SetTrackBar(LabelContrast, TrackBarContrast, CheckBoxContrast, FCamera->Contrast, FCamera->ContrastRange, FCamera->ContrastAuto);

      if (FCamera->ExposureSupported)
        SetTrackBar(LabelExposure, TrackBarExposure, CheckBoxExposure, FCamera->Exposure, FCamera->ExposureRange, FCamera->ExposureAuto);

      if (FCamera->FocusSupported)
        SetTrackBar(LabelFocus, TrackBarFocus, CheckBoxFocus, FCamera->Focus, FCamera->FocusRange, FCamera->FocusAuto);

      if (FCamera->GainSupported)
        SetTrackBar(LabelGain, TrackBarGain, CheckBoxGain, FCamera->Gain, FCamera->GainRange, FCamera->GainAuto);

      if (FCamera->GammaSupported)
        SetTrackBar(LabelGamma, TrackBarGamma, CheckBoxGamma, FCamera->Gamma, FCamera->GammaRange, FCamera->GammaAuto);

      if (FCamera->HueSupported)
        SetTrackBar(LabelHue, TrackBarHue, CheckBoxHue, FCamera->Hue, FCamera->HueRange, FCamera->HueAuto);

      if (FCamera->IrisSupported)
        SetTrackBar(LabelIris, TrackBarIris, CheckBoxIris, FCamera->Iris, FCamera->IrisRange, FCamera->IrisAuto);

      if (FCamera->PanSupported)
        SetTrackBar(LabelPan, TrackBarPan, CheckBoxPan, FCamera->Pan, FCamera->PanRange, FCamera->PanAuto);

      if (FCamera->RollSupported)
        SetTrackBar(LabelRoll, TrackBarRoll, CheckBoxRoll, FCamera->Roll, FCamera->RollRange, FCamera->RollAuto);

      if (FCamera->SaturationSupported)
        SetTrackBar(LabelSaturation, TrackBarSaturation, CheckBoxSaturation, FCamera->Saturation, FCamera->SaturationRange, FCamera->SaturationAuto);

      if (FCamera->SharpnessSupported)
        SetTrackBar(LabelSharpness, TrackBarSharpness, CheckBoxSharpness, FCamera->Sharpness, FCamera->SharpnessRange, FCamera->SharpnessAuto);

      if (FCamera->TiltSupported)
        SetTrackBar(LabelTilt, TrackBarTilt, CheckBoxTilt, FCamera->Tilt, FCamera->TiltRange, FCamera->TiltAuto);

      if (FCamera->WhiteBalanceSupported)
        SetTrackBar(LabelWhiteBalance, TrackBarWhiteBalance, CheckBoxWhiteBalance, FCamera->WhiteBalance, FCamera->WhiteBalanceRange, FCamera->WhiteBalanceAuto);

      if (FCamera->ZoomSupported)
        SetTrackBar(LabelZoom, TrackBarZoom, CheckBoxZoom, FCamera->Zoom, FCamera->ZoomRange, FCamera->ZoomAuto);
    }
  }
  __finally
  {
    TrackBarsSetting = false;
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::StartDevice()
{
  SetTrackBars();
  if (ComboBoxFormat->ItemIndex != -1)
  {
    Timer->Enabled = false;
    TimerObr->Enabled = false;
    FObr->Active = false;
    FCamera->Active = false;
    FCamera->Format = FCamera->SupportedFormats[ComboBoxFormat->ItemIndex];
    PaintBox->Width = FCamera->Format.Width;
    PaintBox->Height = FCamera->Format.Height;
    FObr->Active = true;
    FCamera->Active = true;
    FCamera->Run();
    if (FCamera->CaptureType != ctGrabber)
    {
      Timer->Interval = FCamera->Format.AvgTimePerFrame / 10000;
      Timer->Enabled = true;
    }
    TimerObr->Enabled = true;
    ButtonSaveCurrentImage->Enabled = true;
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::TrackBarChange(TObject *Sender)
{
  if (!TrackBarsSetting)
    if (Sender == TrackBarBacklightCompensation)
      FCamera->BacklightCompensation = floor(TrackBarBacklightCompensation->Value);
    else if (Sender == TrackBarBrightness)
      FCamera->Brightness = floor(TrackBarBrightness->Value);
    else if (Sender == TrackBarColorEnable)
      FCamera->ColorEnable = floor(TrackBarColorEnable->Value);
    else if (Sender == TrackBarContrast)
      FCamera->Contrast = floor(TrackBarContrast->Value);
    else if (Sender == TrackBarExposure)
      FCamera->Exposure = floor(TrackBarExposure->Value);
    else if (Sender == TrackBarFocus)
      FCamera->Focus = floor(TrackBarFocus->Value);
    else if (Sender == TrackBarGain)
      FCamera->Gain = floor(TrackBarGain->Value);
    else if (Sender == TrackBarGamma)
      FCamera->Gamma = floor(TrackBarGamma->Value);
    else if (Sender == TrackBarHue)
      FCamera->Hue = floor(TrackBarHue->Value);
    else if (Sender == TrackBarIris)
      FCamera->Iris = floor(TrackBarIris->Value);
    else if (Sender == TrackBarPan)
      FCamera->Pan = floor(TrackBarPan->Value);
    else if (Sender == TrackBarRoll)
      FCamera->Roll = floor(TrackBarRoll->Value);
    else if (Sender == TrackBarSaturation)
      FCamera->Saturation = floor(TrackBarSaturation->Value);
    else if (Sender == TrackBarSharpness)
      FCamera->Sharpness = floor(TrackBarSharpness->Value);
    else if (Sender == TrackBarTilt)
      FCamera->Tilt = floor(TrackBarTilt->Value);
    else if (Sender == TrackBarWhiteBalance)
      FCamera->WhiteBalance = floor(TrackBarWhiteBalance->Value);
    else if (Sender == TrackBarZoom)
      FCamera->Zoom = floor(TrackBarZoom->Value);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonDefaultValuesClick(TObject *Sender)
{
  try
  {
    if (FCamera->BacklightCompensationSupported)
      FCamera->BacklightCompensation = FCamera->BacklightCompensationRange.Default;

    if (FCamera->BrightnessSupported)
      FCamera->Brightness = FCamera->BrightnessRange.Default;

    if (FCamera->ColorEnableSupported)
      FCamera->ColorEnable = FCamera->ColorEnableRange.Default;

    if (FCamera->ContrastSupported)
      FCamera->Contrast = FCamera->ContrastRange.Default;

    if (FCamera->ExposureSupported)
      FCamera->Exposure = FCamera->ExposureRange.Default;

    if (FCamera->FocusSupported)
      FCamera->Focus = FCamera->FocusRange.Default;

    if (FCamera->GainSupported)
      FCamera->Gain = FCamera->GainRange.Default;

    if (FCamera->GammaSupported)
      FCamera->Gamma = FCamera->GammaRange.Default;

    if (FCamera->HueSupported)
      FCamera->Hue = FCamera->HueRange.Default;

    if (FCamera->IrisSupported)
      FCamera->Iris = FCamera->IrisRange.Default;

    if (FCamera->PanSupported)
      FCamera->Pan = FCamera->PanRange.Default;

    if (FCamera->RollSupported)
      FCamera->Roll = FCamera->RollRange.Default;

    if (FCamera->SaturationSupported)
      FCamera->Saturation = FCamera->SaturationRange.Default;

    if (FCamera->SharpnessSupported)
      FCamera->Sharpness = FCamera->SharpnessRange.Default;

    if (FCamera->TiltSupported)
      FCamera->Tilt = FCamera->TiltRange.Default;

    if (FCamera->WhiteBalanceSupported)
      FCamera->WhiteBalance = FCamera->WhiteBalanceRange.Default;

    if (FCamera->ZoomSupported)
      FCamera->Zoom = FCamera->ZoomRange.Default;
  }
  __finally
  {
    SetTrackBars();
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ButtonSaveCurrentImageClick(TObject *Sender)
{
  FCamera->CurrentImageToFile("image.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::CheckBoxChange(TObject *Sender)
{
  if (!TrackBarsSetting)
  {
    if (Sender == CheckBoxBacklightCompensation)
      FCamera->BacklightCompensationAuto = CheckBoxBacklightCompensation->IsChecked;
    else if (Sender == CheckBoxBrightness)
      FCamera->BrightnessAuto = CheckBoxBrightness->IsChecked;
    else if (Sender == CheckBoxColorEnable)
      FCamera->ColorEnableAuto = CheckBoxColorEnable->IsChecked;
    else if (Sender == CheckBoxContrast)
      FCamera->ContrastAuto = CheckBoxContrast->IsChecked;
    else if (Sender == CheckBoxExposure)
      FCamera->ExposureAuto = CheckBoxExposure->IsChecked;
    else if (Sender == CheckBoxFocus)
      FCamera->FocusAuto = CheckBoxFocus->IsChecked;
    else if (Sender == CheckBoxGain)
      FCamera->GainAuto = CheckBoxGain->IsChecked;
    else if (Sender == CheckBoxGamma)
      FCamera->GammaAuto = CheckBoxGamma->IsChecked;
    else if (Sender == CheckBoxHue)
      FCamera->HueAuto = CheckBoxHue->IsChecked;
    else if (Sender == CheckBoxIris)
      FCamera->IrisAuto = CheckBoxIris->IsChecked;
    else if (Sender == CheckBoxPan)
      FCamera->PanAuto = CheckBoxPan->IsChecked;
    else if (Sender == CheckBoxRoll)
      FCamera->RollAuto = CheckBoxRoll->IsChecked;
    else if (Sender == CheckBoxSaturation)
      FCamera->SaturationAuto = CheckBoxSaturation->IsChecked;
    else if (Sender == CheckBoxSharpness)
      FCamera->SharpnessAuto = CheckBoxSharpness->IsChecked;
    else if (Sender == CheckBoxTilt)
      FCamera->TiltAuto = CheckBoxTilt->IsChecked;
    else if (Sender == CheckBoxWhiteBalance)
      FCamera->WhiteBalanceAuto = CheckBoxWhiteBalance->IsChecked;
    else if (Sender == CheckBoxZoom)
      FCamera->ZoomAuto = CheckBoxZoom->IsChecked;

    SetTrackBars();
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ComboBoxCameraChange(TObject *Sender)
{
  SetFormats();
  SetTrackBars();
  ButtonDefaultValues->Enabled = FCamera->DeviceName.Length() > 0;
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ComboBoxCameraClick(TObject *Sender)
{
  SetDevices();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::ComboBoxFormatChange(TObject *Sender)
{
  TThread::ForceQueue(NULL,
    [this]()
    {
      StartDevice();
    });
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FormCreate(TObject *Sender)
{
  SetDevices();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::PaintBoxPaint(TObject *Sender, TCanvas *Canvas)
{
  using Fmx::Graphics::TBitmap;

  if (FCamera->Active)
  {
    TBitmap *Bitmap = FCamera->CurrentImageToBitmap();
    try
    {
      try
      {
        TRectF Rect = TRectF(0, 0, Bitmap->Width, Bitmap->Height);
        Canvas->DrawBitmap(Bitmap, Rect, Rect, 1.0, true);
      }
      __finally
      {
        delete Bitmap;
      }
    }
    catch (Exception &ex)
    {
      // ignore exceptions
    }
  }
}
//---------------------------------------------------------------------------
BOOL DoInvalidateRect(HWND hWnd, RECT *lpRect, BOOL bErase)
{
  return InvalidateRect(hWnd, lpRect, bErase);
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::InvalidatePaintBox()
{
  HWND Window = Fmx::Platform::Win::FormToHWND(this);
  if (PaintBox != NULL)
  {
    TRectF PaintBoxRect = PaintBox->AbsoluteRect;
    RECT WindowRect;
    WindowRect.left = floor(PaintBoxRect.Left);
    WindowRect.top = floor(PaintBoxRect.Top);
    WindowRect.right = System::Math::Ceil(PaintBoxRect.Right);
    WindowRect.bottom = System::Math::Ceil(PaintBoxRect.Bottom);
    DoInvalidateRect(Window, &WindowRect, false);
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::FCameraImageAvailable(TObject *Sender, double SampleTime)
{
  InvalidatePaintBox();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::TimerTimer(TObject *Sender)
{
  InvalidatePaintBox();
}
//---------------------------------------------------------------------------
void __fastcall TFormMain::TimerObrTimer(TObject *Sender)
{
  Graphics::TBitmap *Bitmap = FCamera->CurrentImageToBitmap();
  try
  {
    FObr->Picture->Assign(Bitmap);
    FObr->Scan();
    if (FObr->BarcodeCount > 0)
    {
      TObrSymbol *Barcode = FObr->Barcode[0];
      LabelBarcode->Text = Barcode->SymbologyName + Barcode->SymbologyAddonName + " " + Barcode->OrientationName + " " + Barcode->DataUtf8;
    }
  }
  __finally
  {
    delete Bitmap;
  }
}
//---------------------------------------------------------------------------

