/* Enter a unique ExecutionPlan */
@Plan:name('$executionPlanName')

/* Enter a unique description for ExecutionPlan */
-- @Plan:description('ExecutionPlan')

/* define streams/tables and write queries here ... */

@Import('org.wso2.geo.StandardSpatialEvents:1.0.0')
define stream dataIn (id string, owner string, latitude double, longitude double, timeStamp long, type string ,speed float, heading float, eventId string);

@Export('iot.per.device.stream.geo.FusedSpatialEvent:1.0.0')
define stream dataOut (id string, owner string, latitude double, longitude double, timeStamp long, type string, speed float, heading float, state string, information string, notify bool );

@Export('iot.per.device.stream.geo.AlertNotifications:1.0.0')
define stream alertsOut (id string, owner string, state string, information string, timeStamp long, latitude double, longitude double, type string);

@IndexBy('id')
define table StationeryTable(id string, timeStamp long);

@IndexBy('id')
define table AlertsTable(id string, stationary bool);

from dataIn
select id, owner, latitude, longitude, timeStamp, type, speed, heading, eventId,geo:within(longitude,latitude,"$geoFenceGeoJSON") as isWithin
insert into innerStreamOne;

from innerStreamOne[isWithin == false]
delete StationeryTable on StationeryTable.id==id;

from innerStreamOne[isWithin == false]
select id, owner, latitude, longitude,timeStamp, type, speed, heading ,eventId , "false"  as isStationary
insert into dataOutStream;

from innerStreamOne[isWithin == true]#geo:stationary(id,longitude,latitude, $fluctuationRadius)
select id, owner, latitude, longitude, timeStamp, type, speed, heading, eventId,stationary
insert into innerStreamTwo;

from innerStreamTwo[innerStreamTwo.stationary == true]
select innerStreamTwo.id, innerStreamTwo.stationary
insert into AlertsTable;

from innerStreamTwo[innerStreamTwo.stationary == false]
delete AlertsTable on AlertsTable.id==id;

from innerStreamTwo[innerStreamTwo.stationary == false]
delete StationeryTable on StationeryTable.id==id;

from innerStreamOne[isWithin == true AND not(AlertsTable.id == innerStreamOne.id in AlertsTable)]
select id, owner, latitude, longitude,timeStamp, type, speed, heading ,eventId , "false"  as isStationary
insert into dataOutStream;

from innerStreamOne[isWithin == true AND AlertsTable.id == innerStreamOne.id in AlertsTable]
insert into innerStreamThree;

from innerStreamThree#window.length(0) join AlertsTable
on innerStreamThree.id == AlertsTable.id
select innerStreamThree.id, innerStreamThree.owner, innerStreamThree.latitude, innerStreamThree.longitude,innerStreamThree.timeStamp, innerStreamThree.type, innerStreamThree.speed, innerStreamThree.heading ,innerStreamThree.eventId
insert into innerStreamFour;

from innerStreamFour[not(StationeryTable.id == innerStreamFour.id in StationeryTable)]
select innerStreamFour.id, innerStreamFour.timeStamp
insert into StationeryTable;

from innerStreamOne[isWithin == true AND not(StationeryTable.id == innerStreamOne.id in StationeryTable)]
select id, owner, latitude, longitude,timeStamp, type, speed, heading ,eventId , "false"  as isStationary
insert into dataOutStream;

from innerStreamOne[isWithin == true AND StationeryTable.id == innerStreamOne.id in StationeryTable]
insert into innerStreamFive;

from innerStreamFive#window.length(0) join StationeryTable
on innerStreamFive.id == StationeryTable.id
select innerStreamFive.id, innerStreamFive.owner, innerStreamFive.latitude, innerStreamFive.longitude,innerStreamFive.timeStamp, innerStreamFive.type, innerStreamFive.speed, innerStreamFive.heading ,innerStreamFive.eventId, StationeryTable.timeStamp as storedTime
insert into innerStreamSix;

from innerStreamSix[(timeStamp - storedTime) >= $stationeryTime]
select id, owner, latitude, longitude,timeStamp, type, speed, heading ,eventId ,"true"  as isStationary
insert into dataOutStream;

from innerStreamSix[(timeStamp - storedTime) < $stationeryTime]
select id, owner, latitude, longitude,timeStamp, type, speed, heading ,eventId ,"false"  as isStationary
insert into dataOutStream;

from dataOutStream[isStationary == 'true']
select id, owner, latitude, longitude,timeStamp, type, speed, heading, "ALERTED" as state, str:concat("The ", type, " device `", id, "` of $owner is in $stationeryName area!") as information, true as notify
insert into dataOut;

from dataOutStream[isStationary == 'false']
select id, owner, latitude, longitude,timeStamp, type, speed, heading, "NORMAL" as state,"" as information, false as notify
insert into dataOut;

from dataOut[notify == true]
select id, owner, state, information, timeStamp, latitude, longitude, type
insert into alertsOut;
