unit WebCamPage;

interface

uses
  Classes, SysUtils, FileUtil, WebPage, HTTPServer, HtmlClasses, SqlDatabase,
  ModuleUser, DateUtils;

type

  { TWebCamPage }

  TWebCamPage = class(TWebPage)
    procedure DataModuleProduce(HandlerData: THTTPHandlerData);
  private
    ImageWidth: Integer;
    ImageHeight: Integer;
    function GetAll(HandlerData: THTTPHandlerData): string;
    function GetSingle(HandlerData: THTTPHandlerData; Id: Integer): string;
    function GetVideoArchive(Id: string): string;
  end;

var
  WebCamPage: TWebCamPage;


implementation

{$R *.lfm}

uses
  Core, Utils, WebSession;


{ TWebCamPage }

procedure TWebCamPage.DataModuleProduce(HandlerData: THTTPHandlerData);
var
  DbRows: TDbRows;
  I: Integer;
  CameraId: Integer;
  SubPageName: string;
  Value: Integer;
  NotFound: Boolean;
  WidthValue: string;
  ModuleUser: TModuleUser;
begin
  with TWebSession(HandlerData) do begin
    ModuleUser := TModuleUser(ModuleManager.FindModuleByName('User'));
    ModuleUser.LoadUserInfo;
    with HtmlDocument.Body, SubItems.AddString do begin
      Text := '';
      CameraId := -1;
      NotFound := False;
      if Request.Path.Count = 2 then begin
        SubPageName := Request.Path[1];
        if TryStrToInt(SubPageName, Value) then
          CameraId := Value else
          NotFound := True;
      end else
      if Request.Path.Count > 2 then NotFound := True;
      if NotFound then begin
        PageNotFound;
        Exit;
      end;

      if HandlerData.Request.Query.TryGetValue('W', WidthValue) then
        ImageWidth := StrToInt(WidthValue)
        else ImageWidth := 640;

      Text := Text + '<table style="width: 100%"><tr><td style="width: 20%" valign="top">' +
        '<strong>Velikost</strong><br/>' +
        '<a href="?W=160">Malá</a><br/> ' +
        '<a href="?W=320">Menší</a><br/> ' +
        '<a href="?W=640">Střední</a><br/> ' +
        '<a href="?W=1024">Větší</a><br/> ' +
        '<a href="?W=1280">Velká</a><br/><br/>';

      Text := Text + '<strong>Místní kamery</strong><br/>';
      Text := Text + MakeLink('Všechny', NavigationLink('/kamery/?W=' + IntToStr(ImageWidth))) + '<br/>';
      try
        DbRows := TDbRows.Create;
        Database.Query(DbRows, 'SELECT * FROM `Webcam` WHERE `Enabled`=1 AND `Public`=1');
        for I := 0 to DbRows.Count - 1 do begin
          Text := Text + MakeLink(DbRows[I].Items['Name'], NavigationLink(
            '/kamery/' + DbRows[I].Items['Id'] + '/?W=' + IntToStr(ImageWidth))) + '<br/>';
        end;
      finally
        DbRows.Free;
      end;

      Text := Text + '<br/><strong>Kamery v okolí:</strong><br />' +
        '<a href="https://www.mestovsetin.cz/webove%2Dkamery/d-480245">Vsetínské kamery</a><br />' +
        '<a href="https://www.huslenky.cz/webkamery%2Dhuslenky/ds-1119/archiv=0&amp;p1=1020">Kamery v Huslenkách</a><br/>' +
        '<a href="https://kamery.hovnet.cz/">Kamery v Hovnetu</a><br/>' +
        '</td><td style="width: 80%" valign="top">';

      if CameraId = -1 then begin
        Text := Text + GetAll(HandlerData);
      end else begin
        Text := Text + GetSingle(HandlerData, CameraId);
      end;
      Text := Text + '</td></tr></table>';
    end;
    GeneratePage(Self);
  end;
end;

function TWebCamPage.GetAll(HandlerData: THTTPHandlerData): string;
var
  DbRows: TDbRows;
  I: Integer;
  ImageWidthThumb: Integer;
  ImageHeightThumb: Integer;
  WebCamImage: string;
begin
  Result := '';
  with TWebSession(HandlerData) do
  try
    DbRows := TDbRows.Create;
    Database.Query(DbRows, 'SELECT * FROM `Webcam` WHERE `Enabled`=1 AND `Public`=1');
    ImageWidthThumb := 160;
    for I := 0 to DbRows.Count - 1 do begin
      ImageHeightThumb := Round(ImageWidthThumb * StrToInt(DbRows[I].Items['Height']) / StrToInt(DbRows[I].Items['Width']));
      WebCamImage := 'images/webcam/' + DbRows[I].Items['ImageName'];
      Result := Result + '<span align="center" valign="middle" style="vertical-align: middle;">' + //DbRows[I].Values['Name'] + '<br/>' +
        '<a href="' + NavigationLink('/kamery/' + DbRows[I].Items['Id'] + '/?W=' + IntToStr(ImageWidth)) + '">' +
        '<img name="theImage" src="' + NavigationLink('/' + WebCamImage) + '" width="' +
        IntToStr(ImageWidthThumb) + '" height="' + IntToStr(ImageHeightThumb) + '" alt="' +
        DbRows[I].Items['Name'] + '"/></a></span> ';
    end;
  finally
    DbRows.Free;
  end;
end;

function TWebCamPage.GetSingle(HandlerData: THTTPHandlerData; Id: Integer): string;
var
  DbRows: TDbRows;
  I: Integer;
  WebCamImage: string;
  RefreshInterval: Integer;
  LastFileDate: string;
  Token: string;
begin
  Result := '';
  with TWebSession(HandlerData) do
  try
    if HandlerData.Request.Query.TryGetValue('Token', Token) then
      else Token := '';

    DbRows := TDbRows.Create;
    Database.Query(DbRows, 'SELECT * FROM `Webcam` WHERE (`Id`=' +
      IntToStr(Id) + ') AND (`Enabled`=1) AND ' +
      '((`Public` = 1) OR ((`Public` = 0) AND (`Token`="' +
      Database.EscapeString(Token) + '")))');
    if DbRows.Count > 0 then begin
      WebCamImage := 'images/webcam/' + DbRows[0].Items['ImageName'];
      RefreshInterval := StrToInt(DbRows[0].Items['ImagePeriod']);
      ImageHeight := Round(ImageWidth * StrToInt(DbRows[0].Items['Height']) / StrToInt(DbRows[0].Items['Width']));

      if FileExists(WebCamImage) then begin
        DateTimeToString(LastFileDate, 'hh:mm:ss d.m.yyyy', FileDateToDateTime(FileAge(WebCamImage)));
        Result := Result + '<script language="JavaScript">' + #13#10 +
          '  var ImageURL= "' + NavigationLink('/' + WebCamImage) + '";' + #13#10 +
          '' + #13#10 +
          '// Force an immediate image load' + #13#10 +
          'var theTimer = setTimeout("reloadImage()", 1);' + #13#10 +
          '' + #13#10 +
          'function reloadImage()' + #13#10 +
          '{' + #13#10 +
          '  theDate = new Date();' + #13#10 +
          '  var url = ImageURL;' + #13#10 +
          '  url += "?dummy=";' + #13#10 +
          '  url += theDate.getTime().toString(10);' + #13#10 +
          '  // The above dummy cgi-parameter enforce a bypass of the browser image cache.' + #13#10 +
          '  // Here we actually load the image' + #13#10 +
          '  document.theImage.src = document.theImageTemp.src;' + #13#10 +
          '  document.theImageTemp.src = url;' + #13#10 +
          '' + #13#10 +
          '  // Reload the image every defined period' + #13#10 +
          '  theTimer = setTimeout("reloadImage()", ' + IntToStr(RefreshInterval * 1000) + ');' + #13#10 +
          '}' + #13#10 +
          '</script>' + #13#10 +

          '<br /><div align="center">' + DbRows[0].Items['Name'] + '<br/>' +
          '<img name="theImageTemp" src="' + NavigationLink('/' + WebCamImage) + '" width="0" height="0" alt="Temp image"/>' +
          '<img name="theImage" src="' + NavigationLink('/' + WebCamImage) + '" width="' + IntToStr(ImageWidth) +
          '" height="' + IntToStr(ImageHeight) + '" alt="' +
          DbRows[0].Items['Name'] + '"/></div>';
      end else Result := Result + '<br />Obrázek nenalezen.<br /><br />';
      Result := Result + '<br/><div align="center">';
      if LastFileDate <> '' then Result := Result + 'Aktualizace: <span id="lasttime">' +
        LastFileDate + '</span>, ';
      Result := Result + 'Perioda: ' + IntToStr(RefreshInterval) + ' sekund, Typ: ' +
        DbRows[0].Items['DeviceType'] + '<br />' +
        '<br/>' + DbRows[0].Items['Description'];
      Result := Result + GetVideoArchive(DbRows[0].Items['Id']) + '</div>';
    end else Result := Result + '<br />Id kamery nenalezeno.<br/><br>';
  finally
    DbRows.Free;
  end;
end;

function TWebCamPage.GetVideoArchive(Id: string): string;
var
  I: Integer;
  Items: TStringList;
  DateStr: string;
  VideoPathFormat: string;
  Date: TDateTime;
  Video: string;
const
  OneDay = 24 * OneHour;
begin
  Result := '';
  VideoPathFormat := 'images/webcam_archive/%s/%s/video.mp4';
  Items := TStringList.Create;
  try
    Date := Now - OneDay;
    repeat
      DateStr := FormatDateTime('yyyy-mm-dd', Date);
      Video := Format(VideoPathFormat, [DateStr, Id]);
      if FileExists(Video) then begin
        Items.Add(DateStr + Items.NameValueSeparator + Video);
        Date := Date - OneDay;
        Continue;
      end else Break;
    until False;

    if Items.Count > 0 then begin
      Result := '<br/>Video archív: <select name="dates" id="dates">';
      for I := 0 to Items.Count - 1 do begin
        Result := Result + '<option value="' + NavigationLink('/' + Items.ValueFromIndex[I]) + '">' + Items.Names[I] + '</option>';
      end;
      Result := Result + '</select>';
      Result := Result + ' <button onclick="var element = document.getElementById(''dates''); window.open(element.value, ''_blank'')">Zobrazit</button>';
    end;
  finally
    Items.Free;
  end;
end;

end.

