// =============
// == CP DIFF ==
// =============

#Include "TextLib" as TL

// Includes
{% include 'core.views/libs/TimeUtils.Script.Txt' %}

// =================
// == MAIN SCRIPT ==
// =================

declare CMlFrame Sector_CPTime_Frame;
declare CMlLabel Sector_CPTime_Data;
declare CMlQuad Sector_CPTime_TimeBg;
declare CMlLabel Sector_CPTime_TimeLabel;
declare CMlLabel Sector_CPTime_TimeIcon;
declare CMlLabel Sector_CPTime_RecordLabel;

declare Integer TotalCheckpoints;
declare Integer CurrentCheckpoint;
declare Integer CurrentLapScore;
declare Integer[] CurrentCheckpointScores;

declare Integer BestScore;
declare Integer[] BestCheckpoints;
declare Text BestSource;

declare Integer HideFrameAt;


Void UpdateInterface() {
  // Current lap sector time.
  declare CurrentCheckpointTime = 0;
  if (GUIPlayer != Null) {
    CurrentCheckpointTime = GUIPlayer.CurCheckpointLapTime;
  }
  if (CurrentCheckpointTime == -1 && CurrentLapScore > 0) {
    CurrentCheckpointTime = CurrentLapScore;
  }

  // Get record cp time.
  declare Integer RecordCpTime;
  if (CurrentCheckpoint > 0 && CurrentCheckpoint <= BestCheckpoints.count) {
    RecordCpTime = BestCheckpoints[CurrentCheckpoint - 1];
  } else if (CurrentCheckpoint > BestCheckpoints.count) {
    RecordCpTime = BestScore;
    if (CurrentCheckpointTime <= 0) {
      CurrentCheckpointTime = CurrentLapScore;
    }
  } else {
    RecordCpTime = 0;
  }

  // Calculate diff.
  declare Integer Difference = 0;
  declare Text DifferencePrefix = "";
  declare Text DifferenceIcon = ""; // Up chevron.
  declare Vec3 DifferenceBackgroundColor = <0., 0., 0.>;

  // Determinate if faster or slower.
  if (CurrentCheckpointTime > 0 && RecordCpTime > 0) {
    Difference = CurrentCheckpointTime - RecordCpTime;

    if (Difference > 0) {
      DifferencePrefix = "$C30";
      DifferenceIcon = ""; // Down. &#xf107;
      DifferenceBackgroundColor = TL::ToColor("C30"); // Red
    } else if (Difference < 0) {
      DifferencePrefix = "$02F";
      DifferenceIcon = ""; // Up. &#xf105;
      DifferenceBackgroundColor = TL::ToColor("02F"); // Blue
    }
  }

  // Fill the time difference labels and backgrounds.
  Sector_CPTime_TimeBg.BgColor = DifferenceBackgroundColor;
  Sector_CPTime_TimeBg.Opacity = 0.5;
  Sector_CPTime_TimeIcon.SetText(DifferenceIcon);
  Sector_CPTime_TimeLabel.SetText(TimeToText(Difference));

  // Best CP (+ source or current if no record)
  if (RecordCpTime > 0) {
    Sector_CPTime_RecordLabel.SetText(BestSource);
  } else if (BestScore > 0) {
    Sector_CPTime_RecordLabel.SetText(BestSource);
  } else {
    Sector_CPTime_RecordLabel.SetText("-");
  }
}

Integer[] ParseCheckpoints(Text RawInput) {
  if (TL::Length(RawInput) == 0) {
    return Integer[];
  }
  declare Integer[] Output;
  declare Text[] Checkpoints = TL::Split(",", RawInput);
  foreach (Check in Checkpoints) {
    Output.add(TL::ToInteger(Check));
  }
  return Output;
}

Void HideDiff() {
  HideFrameAt = 0;
  Sector_CPTime_Frame.Hide();
}

Void ShowDiff() {
  HideFrameAt = Now + 2500;
  Sector_CPTime_Frame.Show();
}

main() {
  // Set variables
  Sector_CPTime_Frame = (Page.GetFirstChild("cp_time_frame") as CMlFrame);
  Sector_CPTime_Data = (Page.GetFirstChild("cp_time_data") as CMlLabel);
  Sector_CPTime_TimeBg = (Page.GetFirstChild("cp_time_diff_quadbg") as CMlQuad);
  Sector_CPTime_TimeLabel = (Page.GetFirstChild("cp_time_diff_time") as CMlLabel);
  Sector_CPTime_TimeIcon = (Page.GetFirstChild("cp_time_diff_icon") as CMlLabel);
  Sector_CPTime_RecordLabel = (Page.GetFirstChild("cp_time_compare_record") as CMlLabel);

  // Score + cps from the records.
  BestScore = TL::ToInteger(Sector_CPTime_Data.DataAttributeGet("record"));
  BestCheckpoints = ParseCheckpoints(Sector_CPTime_Data.DataAttributeGet("record-sectors"));
  BestSource = Sector_CPTime_Data.DataAttributeGet("record-source");

  TotalCheckpoints = MapCheckpointPos.count;
  CurrentCheckpoint = 0;

  HideFrameAt = 0;

  // Initial update to clear the UI.
  UpdateInterface();
  HideDiff();

  // Main Loop.
  while(True) {
    // Check if the CP Diff should be hidden.
    if (HideFrameAt != 0 && HideFrameAt <= Now) {
      HideDiff();
    }

    // Check for pending race events.
    foreach (Event in RaceEvents) {
      // Stop here if player of the event is not the playing or spectating player.
      if (GUIPlayer == Null || Event.Player != GUIPlayer) {
        continue;
      }
      declare Boolean IsSpectating = GUIPlayer != InputPlayer;

      // If the player itself finished faster. Set the new time as PB.
      if (! IsSpectating && Event.IsEndLap && (BestScore <= 0 || Event.LapTime < BestScore)) {
        BestScore = Event.LapTime;
        BestSource = "PB";
        BestCheckpoints = CurrentCheckpointScores;
      }

      if (Event.Type == CTmRaceClientEvent::EType::Respawn) {
        if (GUIPlayer != Null && GUIPlayer.RaceState != CTmMlPlayer::ERaceState::Running) {
          HideDiff();

          CurrentCheckpointScores = Integer[];
          CurrentCheckpoint = 0;
          UpdateInterface();
        }
      }

      if (Event.Type == CTmRaceClientEvent::EType::WayPoint && GUIPlayer != Null) {
        ShowDiff();

        if (CurrentCheckpoint != TotalCheckpoints) {
          CurrentCheckpoint = Event.CheckpointInLap + 1;
          CurrentCheckpointScores.add(GUIPlayer.CurCheckpointLapTime);
        }

        if (Event.IsEndLap) {
          CurrentCheckpoint = TotalCheckpoints + 1;
          CurrentLapScore = Event.LapTime;
        }

        UpdateInterface();

        if (Event.IsEndLap) {
          CurrentCheckpointScores = Integer[];
          CurrentCheckpoint = 0;
        }
      }
    }
    yield;
  }
}
