/*
 * driver-working-time-derived-projections.epl
 *
 * Source-neutral driver working-time derived projection rules over canonical driver activity,
 * vehicle-usage, and support-evidence interval streams. Tachograph is only one source
 * that can produce these canonical input streams.
 */

create schema SignificantDrivingInterval(
    sessionId java.util.UUID,
    driverKey string,
    firstSourceIntervalId string,
    lastSourceIntervalId string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    registrationKey string,
    vehicleKey string
);

create schema DrivingInterruptionInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DailyWeeklyRestCandidateInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DrivingInterruptionVehicleChangeInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DrivingInterruptionVehicleNotChangedInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DailyWeeklyRestCandidateCoverageUnknownResolvedInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DailyWeeklyRestCandidateCoverageCardResolvedInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema DailyWeeklyRestCandidateCoverageInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    cardAbsentCoveragePercent double,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string,
    beginBoundaryOdometerKm java.lang.Long,
    endBoundaryOdometerKm java.lang.Long,
    beginGeoEventId string,
    beginGeoEventDomain string,
    beginGeoOccurredAtEpochSecond java.lang.Long,
    beginLatitude java.lang.Double,
    beginLongitude java.lang.Double,
    beginGeoDistanceSeconds java.lang.Long,
    beginGeoOdometerKm java.lang.Long,
    endGeoEventId string,
    endGeoEventDomain string,
    endGeoOccurredAtEpochSecond java.lang.Long,
    endLatitude java.lang.Double,
    endLongitude java.lang.Double,
    endGeoDistanceSeconds java.lang.Long,
    endGeoOdometerKm java.lang.Long,
    geoEvidenceMovementMeters java.lang.Long,
    geoEvidenceMovementCategory string
);

create schema SupportGeoEvidence(
    sessionId java.util.UUID,
    driverKey string,
    eventId string,
    eventDomain string,
    occurredAtEpochSecond long,
    registrationKey string,
    vehicleKey string,
    latitude java.lang.Double,
    longitude java.lang.Double,
    odometerKm java.lang.Long,
    priority int
);

create schema DailyWeeklyRestCandidateBeginGeoEvidenceCandidate(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    boundaryOdometerKm java.lang.Long,
    eventId string,
    eventDomain string,
    occurredAtEpochSecond long,
    latitude java.lang.Double,
    longitude java.lang.Double,
    odometerKm java.lang.Long,
    odometerDeltaKm java.lang.Long,
    distanceSeconds long,
    rankScore long
);

create schema DailyWeeklyRestCandidateBeginGeoEvidenceBestScore(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    bestRankScore long
);

create schema DailyWeeklyRestCandidateBeginGeoEvidenceResolved(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    eventId string,
    eventDomain string,
    occurredAtEpochSecond long,
    latitude java.lang.Double,
    longitude java.lang.Double,
    odometerKm java.lang.Long,
    distanceSeconds long
);

create schema DailyWeeklyRestCandidateEndGeoEvidenceCandidate(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    boundaryOdometerKm java.lang.Long,
    eventId string,
    eventDomain string,
    occurredAtEpochSecond long,
    latitude java.lang.Double,
    longitude java.lang.Double,
    odometerKm java.lang.Long,
    odometerDeltaKm java.lang.Long,
    distanceSeconds long,
    rankScore long
);

create schema DailyWeeklyRestCandidateBeginBoundaryOdometerCandidate(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    odometerKm java.lang.Long,
    distanceSeconds long,
    rankScore long
);

create schema DailyWeeklyRestCandidateBeginBoundaryOdometerBestScore(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    bestRankScore long
);

create schema DailyWeeklyRestCandidateBeginBoundaryOdometerResolved(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    odometerKm java.lang.Long,
    distanceSeconds long
);

create schema DailyWeeklyRestCandidateEndBoundaryOdometerCandidate(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    odometerKm java.lang.Long,
    distanceSeconds long,
    rankScore long
);

create schema DailyWeeklyRestCandidateEndBoundaryOdometerBestScore(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    bestRankScore long
);

create schema DailyWeeklyRestCandidateEndBoundaryOdometerResolved(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    odometerKm java.lang.Long,
    distanceSeconds long
);

create schema DailyWeeklyRestCandidateEndGeoEvidenceBestScore(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    bestRankScore long
);

create schema DailyWeeklyRestCandidateEndGeoEvidenceResolved(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    eventId string,
    eventDomain string,
    occurredAtEpochSecond long,
    latitude java.lang.Double,
    longitude java.lang.Double,
    odometerKm java.lang.Long,
    distanceSeconds long
);

create schema DailyWeeklyRestCandidateCoverageFinalizationRequest(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long
);

create schema DailyWeeklyRestCandidateCoverageEmittedKey(
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long
);

create context PerDriver partition by driverKey from TachographVehicleUsageIntervalInputEvent;

create schema VuCardAbsentInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    previousUsageIntervalId string,
    nextUsageIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string
);

create schema PotentialHomeOvernightStayInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    cardAbsentCoveragePercent double,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string,
    beginBoundaryOdometerKm java.lang.Long,
    endBoundaryOdometerKm java.lang.Long,
    beginGeoEventId string,
    beginGeoEventDomain string,
    beginGeoOccurredAtEpochSecond java.lang.Long,
    beginLatitude java.lang.Double,
    beginLongitude java.lang.Double,
    beginGeoDistanceSeconds java.lang.Long,
    beginGeoOdometerKm java.lang.Long,
    endGeoEventId string,
    endGeoEventDomain string,
    endGeoOccurredAtEpochSecond java.lang.Long,
    endLatitude java.lang.Double,
    endLongitude java.lang.Double,
    endGeoDistanceSeconds java.lang.Long,
    endGeoOdometerKm java.lang.Long,
    geoEvidenceMovementMeters java.lang.Long,
    geoEvidenceMovementCategory string
);

create schema PotentialInVehicleOvernightStayInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    cardAbsentCoveragePercent double,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string,
    beginBoundaryOdometerKm java.lang.Long,
    endBoundaryOdometerKm java.lang.Long,
    beginGeoEventId string,
    beginGeoEventDomain string,
    beginGeoOccurredAtEpochSecond java.lang.Long,
    beginLatitude java.lang.Double,
    beginLongitude java.lang.Double,
    beginGeoDistanceSeconds java.lang.Long,
    beginGeoOdometerKm java.lang.Long,
    endGeoEventId string,
    endGeoEventDomain string,
    endGeoOccurredAtEpochSecond java.lang.Long,
    endLatitude java.lang.Double,
    endLongitude java.lang.Double,
    endGeoDistanceSeconds java.lang.Long,
    endGeoOdometerKm java.lang.Long,
    geoEvidenceMovementMeters java.lang.Long,
    geoEvidenceMovementCategory string
);

create schema UnclassifiedDailyWeeklyRestCandidateCoverageInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    cardAbsentDurationSeconds long,
    cardAbsentCoveragePercent double,
    previousDrivingSourceIntervalId string,
    nextDrivingSourceIntervalId string,
    previousRegistrationKey string,
    nextRegistrationKey string,
    previousVehicleKey string,
    nextVehicleKey string,
    beginBoundaryOdometerKm java.lang.Long,
    endBoundaryOdometerKm java.lang.Long,
    beginGeoEventId string,
    beginGeoEventDomain string,
    beginGeoOccurredAtEpochSecond java.lang.Long,
    beginLatitude java.lang.Double,
    beginLongitude java.lang.Double,
    beginGeoDistanceSeconds java.lang.Long,
    beginGeoOdometerKm java.lang.Long,
    endGeoEventId string,
    endGeoEventDomain string,
    endGeoOccurredAtEpochSecond java.lang.Long,
    endLatitude java.lang.Double,
    endLongitude java.lang.Double,
    endGeoDistanceSeconds java.lang.Long,
    endGeoOdometerKm java.lang.Long,
    geoEvidenceMovementMeters java.lang.Long,
    geoEvidenceMovementCategory string
);

create schema PotentialInVehicleTripState(
    sessionId java.util.UUID,
    driverKey string,
    tripStartedAtEpochSecond long,
    registrationKey string,
    vehicleKey string,
    containedPotentialInVehicleOvernightStayIntervalCount int,
    containedPotentialInVehicleOvernightStayDurationSeconds long,
    containedCardAbsentDurationSeconds long,
    firstPotentialInVehicleOvernightStayStartedAtEpochSecond long,
    lastPotentialInVehicleOvernightStayEndedAtEpochSecond long,
    firstPreviousDrivingSourceIntervalId string,
    lastNextDrivingSourceIntervalId string
);

create schema PotentialInVehicleTripInterval(
    sessionId java.util.UUID,
    driverKey string,
    startedAtEpochSecond long,
    endedAtEpochSecond long,
    durationSeconds long,
    registrationKey string,
    vehicleKey string,
    containedPotentialInVehicleOvernightStayIntervalCount int,
    containedPotentialInVehicleOvernightStayDurationSeconds long,
    containedCardAbsentDurationSeconds long,
    firstPotentialInVehicleOvernightStayStartedAtEpochSecond long,
    lastPotentialInVehicleOvernightStayEndedAtEpochSecond long,
    firstPreviousDrivingSourceIntervalId string,
    lastNextDrivingSourceIntervalId string
);

create window PreviousRestCandidateCoverageInterval#unique(driverKey) as DailyWeeklyRestCandidateCoverageInterval;

create window OpenPotentialInVehicleTripState#unique(driverKey) as PotentialInVehicleTripState;

create window SupportGeoEvidenceWindow#keepall as SupportGeoEvidence;

create window DailyWeeklyRestCandidateBeginGeoEvidenceCandidateWindow#keepall as DailyWeeklyRestCandidateBeginGeoEvidenceCandidate;
create window DailyWeeklyRestCandidateBeginGeoEvidenceBestScoreWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateBeginGeoEvidenceBestScore;
create window DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateBeginGeoEvidenceResolved;

create window DailyWeeklyRestCandidateEndGeoEvidenceCandidateWindow#keepall as DailyWeeklyRestCandidateEndGeoEvidenceCandidate;
create window DailyWeeklyRestCandidateEndGeoEvidenceBestScoreWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateEndGeoEvidenceBestScore;
create window DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateEndGeoEvidenceResolved;
create window DailyWeeklyRestCandidateBeginBoundaryOdometerCandidateWindow#keepall as DailyWeeklyRestCandidateBeginBoundaryOdometerCandidate;
create window DailyWeeklyRestCandidateBeginBoundaryOdometerBestScoreWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateBeginBoundaryOdometerBestScore;
create window DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateBeginBoundaryOdometerResolved;
create window DailyWeeklyRestCandidateEndBoundaryOdometerCandidateWindow#keepall as DailyWeeklyRestCandidateEndBoundaryOdometerCandidate;
create window DailyWeeklyRestCandidateEndBoundaryOdometerBestScoreWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateEndBoundaryOdometerBestScore;
create window DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateEndBoundaryOdometerResolved;
create window DailyWeeklyRestCandidateCoverageCardResolvedIntervalWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateCoverageCardResolvedInterval;
create window DailyWeeklyRestCandidateCoverageEmittedKeyWindow#unique(driverKey, startedAtEpochSecond, endedAtEpochSecond) as DailyWeeklyRestCandidateCoverageEmittedKey;

insert into SupportGeoEvidenceWindow
select
    sessionId,
    driverKey,
    eventId,
    eventDomain,
    occurredAtEpochSecond,
    registrationKey,
    vehicleKey,
    latitude,
    longitude,
    odometerKm,
    priority
from TachographSupportGeoEvidenceInputEvent;

insert into SignificantDrivingInterval
select
    sessionId,
    driverKey,
    firstSourceIntervalId,
    lastSourceIntervalId,
    startedAtEpochSecond,
    endedAtEpochSecond,
    durationSeconds,
    registrationKey,
    vehicleKey
from TachographActivityIntervalInputEvent(activityType = 'DRIVE', durationSeconds > ${SIGNIFICANT_DRIVING_THRESHOLD_SECONDS});

create window PreviousSignificantDrivingInterval#unique(driverKey) as SignificantDrivingInterval;

on SignificantDrivingInterval as next
insert into DrivingInterruptionInterval
select
    priorInterval.sessionId as sessionId,
    priorInterval.driverKey as driverKey,
    priorInterval.endedAtEpochSecond as startedAtEpochSecond,
    next.startedAtEpochSecond as endedAtEpochSecond,
    next.startedAtEpochSecond - priorInterval.endedAtEpochSecond as durationSeconds,
    priorInterval.lastSourceIntervalId as previousDrivingSourceIntervalId,
    next.firstSourceIntervalId as nextDrivingSourceIntervalId,
    priorInterval.registrationKey as previousRegistrationKey,
    next.registrationKey as nextRegistrationKey,
    priorInterval.vehicleKey as previousVehicleKey,
    next.vehicleKey as nextVehicleKey
from PreviousSignificantDrivingInterval as priorInterval
where priorInterval.driverKey = next.driverKey
  and next.startedAtEpochSecond > priorInterval.endedAtEpochSecond;

@Priority(20)
on SignificantDrivingInterval
delete from PreviousSignificantDrivingInterval;

@Priority(10)
on SignificantDrivingInterval as current
insert into PreviousSignificantDrivingInterval
select *;

insert into DailyWeeklyRestCandidateInterval
select *
from DrivingInterruptionInterval(durationSeconds > ${MINIMUM_REST_PERIOD_THRESHOLD_SECONDS});

insert into DrivingInterruptionVehicleChangeInterval
select *
from DailyWeeklyRestCandidateInterval(
    previousRegistrationKey is not null,
    nextRegistrationKey is not null,
    previousRegistrationKey != nextRegistrationKey
);

insert into DrivingInterruptionVehicleNotChangedInterval
select *
from DailyWeeklyRestCandidateInterval(
    previousRegistrationKey is not null,
    nextRegistrationKey is not null,
    previousRegistrationKey = nextRegistrationKey
);

insert into DailyWeeklyRestCandidateCoverageUnknownResolvedInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    sum(
        case
            when u.startedAtEpochSecond <= c.startedAtEpochSecond and u.endedAtEpochSecond >= c.endedAtEpochSecond
                then c.durationSeconds
            when u.startedAtEpochSecond <= c.startedAtEpochSecond
                then u.endedAtEpochSecond - c.startedAtEpochSecond
            when u.endedAtEpochSecond >= c.endedAtEpochSecond
                then c.endedAtEpochSecond - u.startedAtEpochSecond
            else u.endedAtEpochSecond - u.startedAtEpochSecond
        end
    ) as cardAbsentDurationSeconds,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey
from DailyWeeklyRestCandidateInterval as c unidirectional,
     VuCardAbsentInterval#keepall as u
where u.driverKey = c.driverKey
  and u.startedAtEpochSecond < c.endedAtEpochSecond
  and u.endedAtEpochSecond > c.startedAtEpochSecond
group by
    c.sessionId,
    c.driverKey,
    c.startedAtEpochSecond,
    c.endedAtEpochSecond,
    c.durationSeconds,
    c.previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId,
    c.previousRegistrationKey,
    c.nextRegistrationKey,
    c.previousVehicleKey,
    c.nextVehicleKey;

insert into DailyWeeklyRestCandidateCoverageUnknownResolvedInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    0L as cardAbsentDurationSeconds,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey
from DailyWeeklyRestCandidateInterval as c
where not exists (
    select * from VuCardAbsentInterval#keepall as u
    where u.driverKey = c.driverKey
      and u.startedAtEpochSecond < c.endedAtEpochSecond
      and u.endedAtEpochSecond > c.startedAtEpochSecond
);

insert into DailyWeeklyRestCandidateCoverageCardResolvedInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    c.cardAbsentDurationSeconds as cardAbsentDurationSeconds,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey
from DailyWeeklyRestCandidateCoverageUnknownResolvedInterval as c;

insert into DailyWeeklyRestCandidateCoverageCardResolvedIntervalWindow
select *
from DailyWeeklyRestCandidateCoverageCardResolvedInterval;

@Priority(50)
insert into DailyWeeklyRestCandidateBeginBoundaryOdometerCandidateWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    v.odometerBeginKm as odometerKm,
    case
        when v.startedAtEpochSecond >= c.startedAtEpochSecond
            then v.startedAtEpochSecond - c.startedAtEpochSecond
        else c.startedAtEpochSecond - v.startedAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when v.startedAtEpochSecond >= c.startedAtEpochSecond
                    then v.startedAtEpochSecond - c.startedAtEpochSecond
                else c.startedAtEpochSecond - v.startedAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when v.startedAtEpochSecond >= c.startedAtEpochSecond
                then 0L
            else 1000L
        end
    ) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     TachographVehicleUsageIntervalInputEvent#keepall as v
where v.driverKey = c.driverKey
  and v.odometerBeginKm is not null
  and v.startedAtEpochSecond >= c.startedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and v.startedAtEpochSecond <= c.startedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.previousVehicleKey is not null
        and v.vehicleKey is not null
        and c.previousVehicleKey = v.vehicleKey
        )
        or (
            (c.previousVehicleKey is null or v.vehicleKey is null)
        and c.previousRegistrationKey is not null
        and v.registrationKey is not null
        and c.previousRegistrationKey = v.registrationKey
        )
  );

@Priority(50)
insert into DailyWeeklyRestCandidateBeginBoundaryOdometerCandidateWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    v.odometerEndKm as odometerKm,
    case
        when v.endedAtEpochSecond >= c.startedAtEpochSecond
            then v.endedAtEpochSecond - c.startedAtEpochSecond
        else c.startedAtEpochSecond - v.endedAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when v.endedAtEpochSecond >= c.startedAtEpochSecond
                    then v.endedAtEpochSecond - c.startedAtEpochSecond
                else c.startedAtEpochSecond - v.endedAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when v.endedAtEpochSecond >= c.startedAtEpochSecond
                then 0L
            else 1000L
        end
    ) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     TachographVehicleUsageIntervalInputEvent#keepall as v
where v.driverKey = c.driverKey
  and v.endedAtEpochSecond is not null
  and v.odometerEndKm is not null
  and v.endedAtEpochSecond >= c.startedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and v.endedAtEpochSecond <= c.startedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.previousVehicleKey is not null
        and v.vehicleKey is not null
        and c.previousVehicleKey = v.vehicleKey
        )
        or (
            (c.previousVehicleKey is null or v.vehicleKey is null)
        and c.previousRegistrationKey is not null
        and v.registrationKey is not null
        and c.previousRegistrationKey = v.registrationKey
        )
  );

@Priority(45)
insert into DailyWeeklyRestCandidateBeginBoundaryOdometerBestScoreWindow
select
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond,
    min(rankScore) as bestRankScore
from DailyWeeklyRestCandidateBeginBoundaryOdometerCandidateWindow
group by
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond;

@Priority(40)
insert into DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.odometerKm as odometerKm,
    c.distanceSeconds as distanceSeconds
from DailyWeeklyRestCandidateBeginBoundaryOdometerCandidateWindow as c,
     DailyWeeklyRestCandidateBeginBoundaryOdometerBestScoreWindow as best
where c.driverKey = best.driverKey
  and c.startedAtEpochSecond = best.startedAtEpochSecond
  and c.endedAtEpochSecond = best.endedAtEpochSecond
  and c.rankScore = best.bestRankScore;

@Priority(50)
insert into DailyWeeklyRestCandidateEndBoundaryOdometerCandidateWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    v.odometerBeginKm as odometerKm,
    case
        when v.startedAtEpochSecond >= c.endedAtEpochSecond
            then v.startedAtEpochSecond - c.endedAtEpochSecond
        else c.endedAtEpochSecond - v.startedAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when v.startedAtEpochSecond >= c.endedAtEpochSecond
                    then v.startedAtEpochSecond - c.endedAtEpochSecond
                else c.endedAtEpochSecond - v.startedAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when v.startedAtEpochSecond <= c.endedAtEpochSecond
                then 0L
            else 1000L
        end
    ) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     TachographVehicleUsageIntervalInputEvent#keepall as v
where v.driverKey = c.driverKey
  and v.odometerBeginKm is not null
  and v.startedAtEpochSecond >= c.endedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and v.startedAtEpochSecond <= c.endedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.nextVehicleKey is not null
        and v.vehicleKey is not null
        and c.nextVehicleKey = v.vehicleKey
        )
        or (
            (c.nextVehicleKey is null or v.vehicleKey is null)
        and c.nextRegistrationKey is not null
        and v.registrationKey is not null
        and c.nextRegistrationKey = v.registrationKey
        )
  );

@Priority(50)
insert into DailyWeeklyRestCandidateEndBoundaryOdometerCandidateWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    v.odometerEndKm as odometerKm,
    case
        when v.endedAtEpochSecond >= c.endedAtEpochSecond
            then v.endedAtEpochSecond - c.endedAtEpochSecond
        else c.endedAtEpochSecond - v.endedAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when v.endedAtEpochSecond >= c.endedAtEpochSecond
                    then v.endedAtEpochSecond - c.endedAtEpochSecond
                else c.endedAtEpochSecond - v.endedAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when v.endedAtEpochSecond <= c.endedAtEpochSecond
                then 0L
            else 1000L
        end
    ) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     TachographVehicleUsageIntervalInputEvent#keepall as v
where v.driverKey = c.driverKey
  and v.endedAtEpochSecond is not null
  and v.odometerEndKm is not null
  and v.endedAtEpochSecond >= c.endedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and v.endedAtEpochSecond <= c.endedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.nextVehicleKey is not null
        and v.vehicleKey is not null
        and c.nextVehicleKey = v.vehicleKey
        )
        or (
            (c.nextVehicleKey is null or v.vehicleKey is null)
        and c.nextRegistrationKey is not null
        and v.registrationKey is not null
        and c.nextRegistrationKey = v.registrationKey
        )
  );

@Priority(45)
insert into DailyWeeklyRestCandidateEndBoundaryOdometerBestScoreWindow
select
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond,
    min(rankScore) as bestRankScore
from DailyWeeklyRestCandidateEndBoundaryOdometerCandidateWindow
group by
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond;

@Priority(40)
insert into DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.odometerKm as odometerKm,
    c.distanceSeconds as distanceSeconds
from DailyWeeklyRestCandidateEndBoundaryOdometerCandidateWindow as c,
     DailyWeeklyRestCandidateEndBoundaryOdometerBestScoreWindow as best
where c.driverKey = best.driverKey
  and c.startedAtEpochSecond = best.startedAtEpochSecond
  and c.endedAtEpochSecond = best.endedAtEpochSecond
  and c.rankScore = best.bestRankScore;

@Priority(40)
insert into DailyWeeklyRestCandidateBeginGeoEvidenceCandidateWindow
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    (select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
        where boundary.driverKey = c.driverKey
          and boundary.startedAtEpochSecond = c.startedAtEpochSecond
          and boundary.endedAtEpochSecond = c.endedAtEpochSecond) as boundaryOdometerKm,
    g.eventId as eventId,
    g.eventDomain as eventDomain,
    g.occurredAtEpochSecond as occurredAtEpochSecond,
    g.latitude as latitude,
    g.longitude as longitude,
    g.odometerKm as odometerKm,
    case
        when (
            select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        ) is null
          or g.odometerKm is null
            then null
        when g.odometerKm >= (
            select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        )
            then g.odometerKm - (
                select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
                where boundary.driverKey = c.driverKey
                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
            )
        else (
            select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        ) - g.odometerKm
    end as odometerDeltaKm,
    case
        when g.occurredAtEpochSecond >= c.startedAtEpochSecond
            then g.occurredAtEpochSecond - c.startedAtEpochSecond
        else c.startedAtEpochSecond - g.occurredAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when g.occurredAtEpochSecond >= c.startedAtEpochSecond
                    then g.occurredAtEpochSecond - c.startedAtEpochSecond
                else c.startedAtEpochSecond - g.occurredAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when (
                select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
                where boundary.driverKey = c.driverKey
                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
            ) is not null
             and g.odometerKm is not null
                then (
                    case
                        when g.odometerKm >= (
                            select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
                            where boundary.driverKey = c.driverKey
                              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                        )
                            then g.odometerKm - (
                                select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
                                where boundary.driverKey = c.driverKey
                                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                            )
                        else (
                            select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as boundary
                            where boundary.driverKey = c.driverKey
                              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                        ) - g.odometerKm
                    end
                ) * 10L
            else 9990L
        end
    ) + (
        case
            when g.occurredAtEpochSecond >= c.startedAtEpochSecond
                then 0L
            else 1000L
        end
    ) + (1000L - g.priority) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     SupportGeoEvidenceWindow as g
where g.driverKey = c.driverKey
  and g.occurredAtEpochSecond >= c.startedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and g.occurredAtEpochSecond <= c.startedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.previousVehicleKey is not null
        and g.vehicleKey is not null
        and c.previousVehicleKey = g.vehicleKey
        )
        or (
            (c.previousVehicleKey is null or g.vehicleKey is null)
        and c.previousRegistrationKey is not null
        and g.registrationKey is not null
        and c.previousRegistrationKey = g.registrationKey
        )
  );

@Priority(35)
insert into DailyWeeklyRestCandidateBeginGeoEvidenceBestScoreWindow
select
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond,
    min(rankScore) as bestRankScore
from DailyWeeklyRestCandidateBeginGeoEvidenceCandidateWindow
group by
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond;

@Priority(30)
insert into DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.eventId as eventId,
    c.eventDomain as eventDomain,
    c.occurredAtEpochSecond as occurredAtEpochSecond,
    c.latitude as latitude,
    c.longitude as longitude,
    c.odometerKm as odometerKm,
    c.distanceSeconds as distanceSeconds
from DailyWeeklyRestCandidateBeginGeoEvidenceCandidateWindow as c,
     DailyWeeklyRestCandidateBeginGeoEvidenceBestScoreWindow as best
where c.driverKey = best.driverKey
  and c.startedAtEpochSecond = best.startedAtEpochSecond
  and c.endedAtEpochSecond = best.endedAtEpochSecond
  and c.rankScore = best.bestRankScore;

@Priority(40)
insert into DailyWeeklyRestCandidateEndGeoEvidenceCandidateWindow
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    (select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
        where boundary.driverKey = c.driverKey
          and boundary.startedAtEpochSecond = c.startedAtEpochSecond
          and boundary.endedAtEpochSecond = c.endedAtEpochSecond) as boundaryOdometerKm,
    g.eventId as eventId,
    g.eventDomain as eventDomain,
    g.occurredAtEpochSecond as occurredAtEpochSecond,
    g.latitude as latitude,
    g.longitude as longitude,
    g.odometerKm as odometerKm,
    case
        when (
            select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        ) is null
          or g.odometerKm is null
            then null
        when g.odometerKm >= (
            select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        )
            then g.odometerKm - (
                select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
                where boundary.driverKey = c.driverKey
                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
            )
        else (
            select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
            where boundary.driverKey = c.driverKey
              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
        ) - g.odometerKm
    end as odometerDeltaKm,
    case
        when g.occurredAtEpochSecond >= c.endedAtEpochSecond
            then g.occurredAtEpochSecond - c.endedAtEpochSecond
        else c.endedAtEpochSecond - g.occurredAtEpochSecond
    end as distanceSeconds,
    (
        (
            case
                when g.occurredAtEpochSecond >= c.endedAtEpochSecond
                    then g.occurredAtEpochSecond - c.endedAtEpochSecond
                else c.endedAtEpochSecond - g.occurredAtEpochSecond
            end
        ) * 10000L
    ) + (
        case
            when (
                select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
                where boundary.driverKey = c.driverKey
                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
            ) is not null
             and g.odometerKm is not null
                then (
                    case
                        when g.odometerKm >= (
                            select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
                            where boundary.driverKey = c.driverKey
                              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                        )
                            then g.odometerKm - (
                                select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
                                where boundary.driverKey = c.driverKey
                                  and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                                  and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                            )
                        else (
                            select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as boundary
                            where boundary.driverKey = c.driverKey
                              and boundary.startedAtEpochSecond = c.startedAtEpochSecond
                              and boundary.endedAtEpochSecond = c.endedAtEpochSecond
                        ) - g.odometerKm
                    end
                ) * 10L
            else 9990L
        end
    ) + (
        case
            when g.occurredAtEpochSecond <= c.endedAtEpochSecond
                then 0L
            else 1000L
        end
    ) + (1000L - g.priority) as rankScore
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c unidirectional,
     SupportGeoEvidenceWindow as g
where g.driverKey = c.driverKey
  and g.occurredAtEpochSecond >= c.endedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
  and g.occurredAtEpochSecond <= c.endedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
  and (
        (
            c.nextVehicleKey is not null
        and g.vehicleKey is not null
        and c.nextVehicleKey = g.vehicleKey
        )
        or (
            (c.nextVehicleKey is null or g.vehicleKey is null)
        and c.nextRegistrationKey is not null
        and g.registrationKey is not null
        and c.nextRegistrationKey = g.registrationKey
        )
  );

@Priority(35)
insert into DailyWeeklyRestCandidateEndGeoEvidenceBestScoreWindow
select
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond,
    min(rankScore) as bestRankScore
from DailyWeeklyRestCandidateEndGeoEvidenceCandidateWindow
group by
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond;

@Priority(30)
insert into DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.eventId as eventId,
    c.eventDomain as eventDomain,
    c.occurredAtEpochSecond as occurredAtEpochSecond,
    c.latitude as latitude,
    c.longitude as longitude,
    c.odometerKm as odometerKm,
    c.distanceSeconds as distanceSeconds
from DailyWeeklyRestCandidateEndGeoEvidenceCandidateWindow as c,
     DailyWeeklyRestCandidateEndGeoEvidenceBestScoreWindow as best
where c.driverKey = best.driverKey
  and c.startedAtEpochSecond = best.startedAtEpochSecond
  and c.endedAtEpochSecond = best.endedAtEpochSecond
  and c.rankScore = best.bestRankScore;

@Priority(20)
insert into DailyWeeklyRestCandidateCoverageFinalizationRequest
select
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond
from DailyWeeklyRestCandidateCoverageCardResolvedInterval as c
where not exists (
    select * from SupportGeoEvidenceWindow as g
    where g.driverKey = c.driverKey
      and g.occurredAtEpochSecond >= c.startedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
      and g.occurredAtEpochSecond <= c.startedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
      and (
            (
                c.previousVehicleKey is not null
            and g.vehicleKey is not null
            and c.previousVehicleKey = g.vehicleKey
            )
            or (
                (c.previousVehicleKey is null or g.vehicleKey is null)
            and c.previousRegistrationKey is not null
            and g.registrationKey is not null
            and c.previousRegistrationKey = g.registrationKey
            )
      )
)
and not exists (
    select * from SupportGeoEvidenceWindow as g
    where g.driverKey = c.driverKey
      and g.occurredAtEpochSecond >= c.endedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
      and g.occurredAtEpochSecond <= c.endedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
      and (
            (
                c.nextVehicleKey is not null
            and g.vehicleKey is not null
            and c.nextVehicleKey = g.vehicleKey
            )
            or (
                (c.nextVehicleKey is null or g.vehicleKey is null)
            and c.nextRegistrationKey is not null
            and g.registrationKey is not null
            and c.nextRegistrationKey = g.registrationKey
            )
      )
);

@Priority(20)
on DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
insert into DailyWeeklyRestCandidateCoverageFinalizationRequest
select
    beginGeo.driverKey as driverKey,
    beginGeo.startedAtEpochSecond as startedAtEpochSecond,
    beginGeo.endedAtEpochSecond as endedAtEpochSecond
from DailyWeeklyRestCandidateCoverageCardResolvedIntervalWindow as c
where c.driverKey = beginGeo.driverKey
  and c.startedAtEpochSecond = beginGeo.startedAtEpochSecond
  and c.endedAtEpochSecond = beginGeo.endedAtEpochSecond
  and not exists (
    select * from SupportGeoEvidenceWindow as g
    where g.driverKey = c.driverKey
      and g.occurredAtEpochSecond >= c.endedAtEpochSecond - ${REST_GEO_LOOKBACK_SECONDS}
      and g.occurredAtEpochSecond <= c.endedAtEpochSecond + ${REST_GEO_LOOKAHEAD_SECONDS}
      and (
            (
                c.nextVehicleKey is not null
            and g.vehicleKey is not null
            and c.nextVehicleKey = g.vehicleKey
            )
            or (
                (c.nextVehicleKey is null or g.vehicleKey is null)
            and c.nextRegistrationKey is not null
            and g.registrationKey is not null
            and c.nextRegistrationKey = g.registrationKey
            )
      )
  );

@Priority(20)
on DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
insert into DailyWeeklyRestCandidateCoverageFinalizationRequest
select
    endGeo.driverKey as driverKey,
    endGeo.startedAtEpochSecond as startedAtEpochSecond,
    endGeo.endedAtEpochSecond as endedAtEpochSecond
from DailyWeeklyRestCandidateCoverageCardResolvedIntervalWindow as c
where c.driverKey = endGeo.driverKey
  and c.startedAtEpochSecond = endGeo.startedAtEpochSecond
  and c.endedAtEpochSecond = endGeo.endedAtEpochSecond;

@Priority(10)
insert into DailyWeeklyRestCandidateCoverageInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    c.cardAbsentDurationSeconds as cardAbsentDurationSeconds,
    (c.cardAbsentDurationSeconds * 100.0d) / c.durationSeconds as cardAbsentCoveragePercent,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey,
    (select odometerKm from DailyWeeklyRestCandidateBeginBoundaryOdometerResolvedWindow as beginBoundary
        where beginBoundary.driverKey = c.driverKey
          and beginBoundary.startedAtEpochSecond = c.startedAtEpochSecond
          and beginBoundary.endedAtEpochSecond = c.endedAtEpochSecond) as beginBoundaryOdometerKm,
    (select odometerKm from DailyWeeklyRestCandidateEndBoundaryOdometerResolvedWindow as endBoundary
        where endBoundary.driverKey = c.driverKey
          and endBoundary.startedAtEpochSecond = c.startedAtEpochSecond
          and endBoundary.endedAtEpochSecond = c.endedAtEpochSecond) as endBoundaryOdometerKm,
    (select eventId from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginGeoEventId,
    (select eventDomain from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginGeoEventDomain,
    (select occurredAtEpochSecond from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginGeoOccurredAtEpochSecond,
    (select latitude from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginLatitude,
    (select longitude from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginLongitude,
    (select distanceSeconds from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginGeoDistanceSeconds,
    (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
        where beginGeo.driverKey = c.driverKey
          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) as beginGeoOdometerKm,
    (select eventId from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endGeoEventId,
    (select eventDomain from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endGeoEventDomain,
    (select occurredAtEpochSecond from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endGeoOccurredAtEpochSecond,
    (select latitude from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endLatitude,
    (select longitude from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endLongitude,
    (select distanceSeconds from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endGeoDistanceSeconds,
    (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
        where endGeo.driverKey = c.driverKey
          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) as endGeoOdometerKm,
    case
        when (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
            where beginGeo.driverKey = c.driverKey
              and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) is null
          or (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
            where endGeo.driverKey = c.driverKey
              and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) is null
            then null
        when (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
            where endGeo.driverKey = c.driverKey
              and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
          >=
          (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
            where beginGeo.driverKey = c.driverKey
              and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
            then (
                (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                    where endGeo.driverKey = c.driverKey
                      and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                -
                (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                    where beginGeo.driverKey = c.driverKey
                      and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
            ) * 1000L
        else (
            (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                where beginGeo.driverKey = c.driverKey
                  and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                  and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
            -
            (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                where endGeo.driverKey = c.driverKey
                  and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                  and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
        ) * 1000L
    end as geoEvidenceMovementMeters,
    case
        when (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
            where beginGeo.driverKey = c.driverKey
              and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond) is null
          or (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
            where endGeo.driverKey = c.driverKey
              and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
              and endGeo.endedAtEpochSecond = c.endedAtEpochSecond) is null
            then 'UNKNOWN'
        when (
            case
                when (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                    where endGeo.driverKey = c.driverKey
                      and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                  >=
                  (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                    where beginGeo.driverKey = c.driverKey
                      and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    then (
                        (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                            where endGeo.driverKey = c.driverKey
                              and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                              and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                        -
                        (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                            where beginGeo.driverKey = c.driverKey
                              and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                              and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    ) * 1000L
                else (
                    (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                        where beginGeo.driverKey = c.driverKey
                          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    -
                    (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                        where endGeo.driverKey = c.driverKey
                          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                ) * 1000L
            end
        ) <= ${REST_GEO_STATIONARY_MAX_METERS}
            then 'STATIONARY'
        when (
            case
                when (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                    where endGeo.driverKey = c.driverKey
                      and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                  >=
                  (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                    where beginGeo.driverKey = c.driverKey
                      and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                      and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    then (
                        (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                            where endGeo.driverKey = c.driverKey
                              and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                              and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                        -
                        (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                            where beginGeo.driverKey = c.driverKey
                              and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                              and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    ) * 1000L
                else (
                    (select odometerKm from DailyWeeklyRestCandidateBeginGeoEvidenceResolvedWindow as beginGeo
                        where beginGeo.driverKey = c.driverKey
                          and beginGeo.startedAtEpochSecond = c.startedAtEpochSecond
                          and beginGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                    -
                    (select odometerKm from DailyWeeklyRestCandidateEndGeoEvidenceResolvedWindow as endGeo
                        where endGeo.driverKey = c.driverKey
                          and endGeo.startedAtEpochSecond = c.startedAtEpochSecond
                          and endGeo.endedAtEpochSecond = c.endedAtEpochSecond)
                ) * 1000L
            end
        ) <= ${REST_GEO_MINOR_MOVEMENT_MAX_METERS}
            then 'MINOR'
        else 'MOVED'
    end as geoEvidenceMovementCategory
from DailyWeeklyRestCandidateCoverageFinalizationRequest as request unidirectional,
     DailyWeeklyRestCandidateCoverageCardResolvedIntervalWindow as c
where c.driverKey = request.driverKey
  and c.startedAtEpochSecond = request.startedAtEpochSecond
  and c.endedAtEpochSecond = request.endedAtEpochSecond
  and not exists (
        select * from DailyWeeklyRestCandidateCoverageEmittedKeyWindow as emitted
        where emitted.driverKey = request.driverKey
          and emitted.startedAtEpochSecond = request.startedAtEpochSecond
          and emitted.endedAtEpochSecond = request.endedAtEpochSecond
  );

insert into DailyWeeklyRestCandidateCoverageEmittedKeyWindow
select
    driverKey,
    startedAtEpochSecond,
    endedAtEpochSecond
from DailyWeeklyRestCandidateCoverageInterval;

context PerDriver
create window PreviousVehicleUsageInterval#lastevent as TachographVehicleUsageIntervalInputEvent;

@Priority(30)
context PerDriver
on TachographVehicleUsageIntervalInputEvent as next
insert into VuCardAbsentInterval
select
    priorInterval.sessionId as sessionId,
    priorInterval.driverKey as driverKey,
    priorInterval.endedAtEpochSecond + 1L as startedAtEpochSecond,
    next.startedAtEpochSecond as endedAtEpochSecond,
    next.startedAtEpochSecond - (priorInterval.endedAtEpochSecond + 1L) as durationSeconds,
    priorInterval.lastSourceIntervalId as previousUsageIntervalId,
    next.firstSourceIntervalId as nextUsageIntervalId,
    priorInterval.registrationKey as previousRegistrationKey,
    next.registrationKey as nextRegistrationKey,
    priorInterval.vehicleKey as previousVehicleKey,
    next.vehicleKey as nextVehicleKey
from PreviousVehicleUsageInterval as priorInterval
where priorInterval.endedAt is not null
  and next.startedAt is not null
  and next.startedAtEpochSecond > priorInterval.endedAtEpochSecond + 1L;

@Priority(20)
context PerDriver
on TachographVehicleUsageIntervalInputEvent
delete from PreviousVehicleUsageInterval;

@Priority(10)
context PerDriver
on TachographVehicleUsageIntervalInputEvent as current
insert into PreviousVehicleUsageInterval
select *;

insert into PotentialHomeOvernightStayInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    c.cardAbsentDurationSeconds as cardAbsentDurationSeconds,
    c.cardAbsentCoveragePercent as cardAbsentCoveragePercent,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey,
    c.beginBoundaryOdometerKm as beginBoundaryOdometerKm,
    c.endBoundaryOdometerKm as endBoundaryOdometerKm,
    c.beginGeoEventId as beginGeoEventId,
    c.beginGeoEventDomain as beginGeoEventDomain,
    c.beginGeoOccurredAtEpochSecond as beginGeoOccurredAtEpochSecond,
    c.beginLatitude as beginLatitude,
    c.beginLongitude as beginLongitude,
    c.beginGeoDistanceSeconds as beginGeoDistanceSeconds,
    c.beginGeoOdometerKm as beginGeoOdometerKm,
    c.endGeoEventId as endGeoEventId,
    c.endGeoEventDomain as endGeoEventDomain,
    c.endGeoOccurredAtEpochSecond as endGeoOccurredAtEpochSecond,
    c.endLatitude as endLatitude,
    c.endLongitude as endLongitude,
    c.endGeoDistanceSeconds as endGeoDistanceSeconds,
    c.endGeoOdometerKm as endGeoOdometerKm,
    c.geoEvidenceMovementMeters as geoEvidenceMovementMeters,
    c.geoEvidenceMovementCategory as geoEvidenceMovementCategory
from DailyWeeklyRestCandidateCoverageInterval as c
where c.previousRegistrationKey is not null
  and c.nextRegistrationKey is not null
  and c.previousRegistrationKey != c.nextRegistrationKey
  and c.cardAbsentDurationSeconds * 100L >= c.durationSeconds * 95L;

insert into PotentialInVehicleOvernightStayInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    c.cardAbsentDurationSeconds as cardAbsentDurationSeconds,
    c.cardAbsentCoveragePercent as cardAbsentCoveragePercent,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey,
    c.beginBoundaryOdometerKm as beginBoundaryOdometerKm,
    c.endBoundaryOdometerKm as endBoundaryOdometerKm,
    c.beginGeoEventId as beginGeoEventId,
    c.beginGeoEventDomain as beginGeoEventDomain,
    c.beginGeoOccurredAtEpochSecond as beginGeoOccurredAtEpochSecond,
    c.beginLatitude as beginLatitude,
    c.beginLongitude as beginLongitude,
    c.beginGeoDistanceSeconds as beginGeoDistanceSeconds,
    c.beginGeoOdometerKm as beginGeoOdometerKm,
    c.endGeoEventId as endGeoEventId,
    c.endGeoEventDomain as endGeoEventDomain,
    c.endGeoOccurredAtEpochSecond as endGeoOccurredAtEpochSecond,
    c.endLatitude as endLatitude,
    c.endLongitude as endLongitude,
    c.endGeoDistanceSeconds as endGeoDistanceSeconds,
    c.endGeoOdometerKm as endGeoOdometerKm,
    c.geoEvidenceMovementMeters as geoEvidenceMovementMeters,
    c.geoEvidenceMovementCategory as geoEvidenceMovementCategory
from DailyWeeklyRestCandidateCoverageInterval as c
where c.previousRegistrationKey is not null
  and c.nextRegistrationKey is not null
  and c.previousRegistrationKey = c.nextRegistrationKey
  and c.cardAbsentDurationSeconds = 0L;

insert into UnclassifiedDailyWeeklyRestCandidateCoverageInterval
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    c.startedAtEpochSecond as startedAtEpochSecond,
    c.endedAtEpochSecond as endedAtEpochSecond,
    c.durationSeconds as durationSeconds,
    c.cardAbsentDurationSeconds as cardAbsentDurationSeconds,
    c.cardAbsentCoveragePercent as cardAbsentCoveragePercent,
    c.previousDrivingSourceIntervalId as previousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as nextDrivingSourceIntervalId,
    c.previousRegistrationKey as previousRegistrationKey,
    c.nextRegistrationKey as nextRegistrationKey,
    c.previousVehicleKey as previousVehicleKey,
    c.nextVehicleKey as nextVehicleKey,
    c.beginBoundaryOdometerKm as beginBoundaryOdometerKm,
    c.endBoundaryOdometerKm as endBoundaryOdometerKm,
    c.beginGeoEventId as beginGeoEventId,
    c.beginGeoEventDomain as beginGeoEventDomain,
    c.beginGeoOccurredAtEpochSecond as beginGeoOccurredAtEpochSecond,
    c.beginLatitude as beginLatitude,
    c.beginLongitude as beginLongitude,
    c.beginGeoDistanceSeconds as beginGeoDistanceSeconds,
    c.beginGeoOdometerKm as beginGeoOdometerKm,
    c.endGeoEventId as endGeoEventId,
    c.endGeoEventDomain as endGeoEventDomain,
    c.endGeoOccurredAtEpochSecond as endGeoOccurredAtEpochSecond,
    c.endLatitude as endLatitude,
    c.endLongitude as endLongitude,
    c.endGeoDistanceSeconds as endGeoDistanceSeconds,
    c.endGeoOdometerKm as endGeoOdometerKm,
    c.geoEvidenceMovementMeters as geoEvidenceMovementMeters,
    c.geoEvidenceMovementCategory as geoEvidenceMovementCategory
from DailyWeeklyRestCandidateCoverageInterval as c
where not (
        c.previousRegistrationKey is not null
    and c.nextRegistrationKey is not null
    and c.previousRegistrationKey != c.nextRegistrationKey
    and c.cardAbsentDurationSeconds * 100L >= c.durationSeconds * 95L
)
  and not (
        c.previousRegistrationKey is not null
    and c.nextRegistrationKey is not null
    and c.previousRegistrationKey = c.nextRegistrationKey
    and c.cardAbsentDurationSeconds = 0L
);

@Priority(40)
on DailyWeeklyRestCandidateCoverageInterval as c
insert into PotentialInVehicleTripInterval
select
    s.sessionId as sessionId,
    s.driverKey as driverKey,
    s.tripStartedAtEpochSecond as startedAtEpochSecond,
    c.startedAtEpochSecond as endedAtEpochSecond,
    c.startedAtEpochSecond - s.tripStartedAtEpochSecond as durationSeconds,
    s.registrationKey as registrationKey,
    s.vehicleKey as vehicleKey,
    s.containedPotentialInVehicleOvernightStayIntervalCount as containedPotentialInVehicleOvernightStayIntervalCount,
    s.containedPotentialInVehicleOvernightStayDurationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
    s.containedCardAbsentDurationSeconds as containedCardAbsentDurationSeconds,
    s.firstPotentialInVehicleOvernightStayStartedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
    s.lastPotentialInVehicleOvernightStayEndedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
    s.firstPreviousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
    s.lastNextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
from OpenPotentialInVehicleTripState as s
where s.driverKey = c.driverKey
  and c.startedAtEpochSecond > s.tripStartedAtEpochSecond
  and (
        not (
                c.previousRegistrationKey is not null
            and c.nextRegistrationKey is not null
            and c.previousRegistrationKey = c.nextRegistrationKey
            and c.cardAbsentDurationSeconds = 0L
        )
        or s.registrationKey != c.previousRegistrationKey
        or (
                s.vehicleKey is not null
            and c.previousVehicleKey is not null
            and s.vehicleKey != c.previousVehicleKey
        )
  );

@Priority(35)
on DailyWeeklyRestCandidateCoverageInterval as c
delete from OpenPotentialInVehicleTripState as s
where s.driverKey = c.driverKey
  and not (
        c.previousRegistrationKey is not null
    and c.nextRegistrationKey is not null
    and c.previousRegistrationKey = c.nextRegistrationKey
    and c.cardAbsentDurationSeconds = 0L
  );

@Priority(30)
on DailyWeeklyRestCandidateCoverageInterval as c
insert into OpenPotentialInVehicleTripState
select
    s.sessionId as sessionId,
    s.driverKey as driverKey,
    s.tripStartedAtEpochSecond as tripStartedAtEpochSecond,
    s.registrationKey as registrationKey,
    s.vehicleKey as vehicleKey,
    s.containedPotentialInVehicleOvernightStayIntervalCount + 1 as containedPotentialInVehicleOvernightStayIntervalCount,
    s.containedPotentialInVehicleOvernightStayDurationSeconds + c.durationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
    s.containedCardAbsentDurationSeconds + c.cardAbsentDurationSeconds as containedCardAbsentDurationSeconds,
    s.firstPotentialInVehicleOvernightStayStartedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
    c.endedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
    s.firstPreviousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
from OpenPotentialInVehicleTripState as s
where s.driverKey = c.driverKey
  and c.previousRegistrationKey is not null
  and c.nextRegistrationKey is not null
  and c.previousRegistrationKey = c.nextRegistrationKey
  and c.cardAbsentDurationSeconds = 0L
  and s.registrationKey = c.previousRegistrationKey
  and (
        s.vehicleKey is null
     or c.previousVehicleKey is null
     or s.vehicleKey = c.previousVehicleKey
  );

@Priority(20)
on DailyWeeklyRestCandidateCoverageInterval as c
insert into OpenPotentialInVehicleTripState
select
    c.sessionId as sessionId,
    c.driverKey as driverKey,
    priorCoverage.endedAtEpochSecond as tripStartedAtEpochSecond,
    c.previousRegistrationKey as registrationKey,
    case
        when c.previousVehicleKey is not null then c.previousVehicleKey
        else c.nextVehicleKey
    end as vehicleKey,
    1 as containedPotentialInVehicleOvernightStayIntervalCount,
    c.durationSeconds as containedPotentialInVehicleOvernightStayDurationSeconds,
    c.cardAbsentDurationSeconds as containedCardAbsentDurationSeconds,
    c.startedAtEpochSecond as firstPotentialInVehicleOvernightStayStartedAtEpochSecond,
    c.endedAtEpochSecond as lastPotentialInVehicleOvernightStayEndedAtEpochSecond,
    c.previousDrivingSourceIntervalId as firstPreviousDrivingSourceIntervalId,
    c.nextDrivingSourceIntervalId as lastNextDrivingSourceIntervalId
from PreviousRestCandidateCoverageInterval as priorCoverage
where priorCoverage.driverKey = c.driverKey
  and c.previousRegistrationKey is not null
  and c.nextRegistrationKey is not null
  and c.previousRegistrationKey = c.nextRegistrationKey
  and c.cardAbsentDurationSeconds = 0L
  and not exists (
        select * from OpenPotentialInVehicleTripState as s
        where s.driverKey = c.driverKey
          and s.registrationKey = c.previousRegistrationKey
          and (
                s.vehicleKey is null
             or c.previousVehicleKey is null
             or s.vehicleKey = c.previousVehicleKey
          )
  );

@Priority(10)
on DailyWeeklyRestCandidateCoverageInterval
delete from PreviousRestCandidateCoverageInterval;

@Priority(5)
on DailyWeeklyRestCandidateCoverageInterval as current
insert into PreviousRestCandidateCoverageInterval
select *;

@name('drivingInterruptionIntervals')
select * from DrivingInterruptionInterval;

@name('dailyWeeklyRestCandidateIntervals')
select * from DailyWeeklyRestCandidateInterval;

@name('dailyWeeklyRestCandidateCoverageIntervals')
select * from DailyWeeklyRestCandidateCoverageInterval;

@name('drivingInterruptionVehicleChangeIntervals')
select * from DrivingInterruptionVehicleChangeInterval;

@name('vuCardAbsentIntervals')
select * from VuCardAbsentInterval;

@name('potentialHomeOvernightStayIntervals')
select * from PotentialHomeOvernightStayInterval;

@name('potentialInVehicleOvernightStayIntervals')
select * from PotentialInVehicleOvernightStayInterval;

@name('potentialInVehicleTripIntervals')
select * from PotentialInVehicleTripInterval;

@name('unclassifiedDailyWeeklyRestCandidateCoverageIntervals')
select * from UnclassifiedDailyWeeklyRestCandidateCoverageInterval;
