syntax = "proto2";

import "jaiabot/messages/geographic_coordinate.proto";
import "dccl/option_extensions.proto";
import "goby/middleware/protobuf/gpsd.proto";
import "jaiabot/messages/option_extensions.proto";

package jaiabot.protobuf;

enum MissionState
{
    PRE_DEPLOYMENT__STARTING_UP = 0 [(jaia.ev).rest_api.presence = GUARANTEED];
    PRE_DEPLOYMENT__IDLE = 1 [(jaia.ev).rest_api.presence = GUARANTEED];
    PRE_DEPLOYMENT__SELF_TEST = 2 [(jaia.ev).rest_api.presence = GUARANTEED];
    PRE_DEPLOYMENT__FAILED = 3 [(jaia.ev).rest_api.presence = GUARANTEED];
    PRE_DEPLOYMENT__WAIT_FOR_MISSION_PLAN = 4
        [(jaia.ev).rest_api.presence = GUARANTEED];
    PRE_DEPLOYMENT__READY = 5 [(jaia.ev).rest_api.presence = GUARANTEED];

    IN_MISSION__UNDERWAY__REPLAN = 100
        [(jaia.ev).rest_api.presence = GUARANTEED];

    IN_MISSION__UNDERWAY__MOVEMENT__TRANSIT = 110
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__MOVEMENT__REMOTE_CONTROL__SETPOINT = 112
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__MOVEMENT__REMOTE_CONTROL__STATION_KEEP = 113
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__MOVEMENT__REMOTE_CONTROL__SURFACE_DRIFT = 114
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__MOVEMENT__TRAIL = 115
        [(jaia.ev).rest_api.presence = GUARANTEED];

    IN_MISSION__UNDERWAY__TASK__STATION_KEEP = 120
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__SURFACE_DRIFT = 121
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__DIVE_PREP = 123
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__POWERED_DESCENT = 124
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__HOLD = 125
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__UNPOWERED_ASCENT = 126
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__POWERED_ASCENT = 127
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__REACQUIRE_GPS = 128
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__SURFACE_DRIFT = 129
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__DIVE__CONSTANT_HEADING = 130
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__TASK__CONSTANT_HEADING = 131
        [(jaia.ev).rest_api.presence = GUARANTEED];

    IN_MISSION__UNDERWAY__RECOVERY__TRANSIT = 140
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__RECOVERY__STATION_KEEP = 141
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__UNDERWAY__RECOVERY__STOPPED = 142
        [(jaia.ev).rest_api.presence = GUARANTEED];

    IN_MISSION__UNDERWAY__ABORT = 150;

    IN_MISSION__PAUSE__IMU_RESTART = 160;
    IN_MISSION__PAUSE__REACQUIRE_GPS = 161
        [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__PAUSE__MANUAL = 162 [(jaia.ev).rest_api.presence = GUARANTEED];
    IN_MISSION__PAUSE__RESOLVE_NO_FORWARD_PROGRESS = 163;

    POST_DEPLOYMENT__RECOVERED = 200 [(jaia.ev).rest_api.presence = GUARANTEED];
    POST_DEPLOYMENT__DATA_OFFLOAD = 202
        [(jaia.ev).rest_api.presence = GUARANTEED];
    POST_DEPLOYMENT__IDLE = 203 [(jaia.ev).rest_api.presence = GUARANTEED];
    POST_DEPLOYMENT__SHUTTING_DOWN = 204
        [(jaia.ev).rest_api.presence = GUARANTEED];
    POST_DEPLOYMENT__FAILED = 205 [(jaia.ev).rest_api.presence = GUARANTEED];
}

message Speeds
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    optional double transit = 1 [
        default = 2,
        (dccl.field) = {
            min: 0.1,
            max: 3.0,
            precision: 1,
            units { base_dimensions: "LT^-1" }
        }
    ];
    optional double stationkeep_outer = 2 [
        default = 0.5,
        (dccl.field) = {
            min: 0.1,
            max: 3.0,
            precision: 1,
            units { base_dimensions: "LT^-1" }
        }
    ];
}

message BottomDepthSafetyParams
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    required double constant_heading = 1 [
        default = 0,
        (dccl.field) = {
            min: 0
            max: 360
            precision: 0
            units { derived_dimensions: "plane_angle" system: "angle::degree" }
        }
    ];

    required int32 constant_heading_time = 2 [
        default = 0,
        (dccl.field) = {
            min: 0
            max: 360
            precision: 0
            units { base_dimensions: "T" }
        }
    ];

    required double constant_heading_speed = 3 [
        default = 2,
        (dccl.field) = {
            min: 0,
            max: 3.0,
            precision: 1,
            units { base_dimensions: "LT^-1" }
        }
    ];

    required double safety_depth = 4 [
        default = -1,
        (dccl.field) = {
            min: -1,
            max: 60,
            precision: 1,
            units { base_dimensions: "LT^-1" }
        }
    ];
}

message MissionReport
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    required MissionState state = 10;
    optional int32 active_goal = 11;
    optional GeographicCoordinate active_goal_location = 12;
    optional double distance_to_active_goal = 13 [(dccl.field) = {
        min: 0
        max: 1000
        precision: 1
        units: { derived_dimensions: "length" }
    }];
    optional uint32 active_goal_timeout = 14 [(dccl.field) = {
        min: 0
        max: 3600
        precision: 0
        units { base_dimensions: "T" }
    }];
    optional int32 data_offload_percentage = 15
        [(dccl.field) = { min: 0 max: 100 precision: 0 }];
    optional int32 repeat_index = 16
        [(dccl.field) = { min: 0 max: 1000 precision: 0 }];
}

message MissionTask
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    enum TaskType
    {
        NONE = 0 [(jaia.ev).rest_api.presence = GUARANTEED];
        DIVE = 1 [(jaia.ev).rest_api.presence = GUARANTEED];
        STATION_KEEP = 2 [(jaia.ev).rest_api.presence = GUARANTEED];
        SURFACE_DRIFT = 3 [(jaia.ev).rest_api.presence = GUARANTEED];
        CONSTANT_HEADING = 4 [(jaia.ev).rest_api.presence = GUARANTEED];
    }
    optional TaskType type = 1
        [default = NONE, (jaia.field).rest_api.presence = GUARANTEED];

    message DiveParameters
    {
        optional double max_depth = 1 [
            default = 50,
            (dccl.field) = {
                min: 0
                max: 50
                precision: 1
                units { base_dimensions: "L" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
        optional double depth_interval = 2 [
            default = inf,
            (dccl.field) = {
                min: 0.1
                max: 50
                precision: 1
                units { base_dimensions: "L" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
        optional double hold_time = 3 [
            default = 0,
            (dccl.field) = {
                min: 0
                max: 80
                precision: 0
                units { base_dimensions: "T" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
        optional bool bottom_dive = 4
            [default = false, (jaia.field).rest_api.presence = GUARANTEED];
    }

    // for type == DIVE
    optional DiveParameters dive = 2
        [(jaia.field).rest_api.presence = GUARANTEED];

    message DriftParameters
    {
        optional int32 drift_time = 3 [
            default = 0,
            (dccl.field) = {
                min: 0
                max: 3600
                precision: -1
                units { base_dimensions: "T" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
    }

    // for type == SURFACE_DRIFT and type == DIVE
    optional DriftParameters surface_drift = 3
        [(jaia.field).rest_api.presence = GUARANTEED];

    message ConstantHeadingParameters
    {
        optional double constant_heading = 1 [
            (dccl.field) = {
                min: 0
                max: 360
                precision: 0
                units {
                    derived_dimensions: "plane_angle"
                    system: "angle::degree"
                }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];

        optional int32 constant_heading_time = 2 [
            default = 0,
            (dccl.field) = {
                min: 0
                max: 3600
                precision: -1
                units { base_dimensions: "T" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];

        optional double constant_heading_speed = 3 [
            default = 2,
            (dccl.field) = {
                min: 0.1,
                max: 3.0,
                precision: 1,
                units { base_dimensions: "LT^-1" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
    }

    // for type == CONSTANT_HEADING
    optional ConstantHeadingParameters constant_heading = 4
        [(jaia.field).rest_api.presence = GUARANTEED];
    optional bool start_echo = 5
        [default = false, (jaia.field).rest_api.presence = GUARANTEED];

    message StationKeepParameters
    {
        optional int32 station_keep_time = 1 [
            default = 10,
            (dccl.field) = {
                min: 0,
                max: 3600,
                precision: -1,
                units { base_dimensions: "T" }
            },
            (jaia.field).rest_api.presence = GUARANTEED
        ];
    }

    // for type == STATION_KEEP
    optional StationKeepParameters station_keep = 6
        [(jaia.field).rest_api.presence = GUARANTEED];
}

message MissionPlan
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    enum MissionStart
    {
        START_IMMEDIATELY = 1 [(jaia.ev).rest_api.presence = GUARANTEED];
        START_ON_COMMAND = 2 [(jaia.ev).rest_api.presence = GUARANTEED];
        // START_IN_WATER_DETECT = 3;
        // START_AFTER_DELAY = 4;
    }
    optional MissionStart start = 1 [
        default = START_ON_COMMAND,
        (jaia.field).rest_api.presence = GUARANTEED
    ];

    enum MovementType
    {
        TRANSIT = 1 [(jaia.ev).rest_api.presence = GUARANTEED];
        REMOTE_CONTROL = 2 [(jaia.ev).rest_api.presence = GUARANTEED];
        TRAIL = 3 [(jaia.ev).rest_api.presence = GUARANTEED];
    }
    optional MovementType movement = 2
        [default = TRANSIT, (jaia.field).rest_api.presence = GUARANTEED];

    message Goal
    {
        optional string name = 1 [(dccl.field).omit = true];
        required GeographicCoordinate location = 2
            [(jaia.field).rest_api.presence = GUARANTEED];
        optional MissionTask task = 3
            [(jaia.field).rest_api.presence = GUARANTEED];
        optional bool moveWptMode = 4;
    }

    repeated Goal goal = 3 [
        (dccl.field).max_repeat = 10,
        (jaia.field).rest_api.presence = GUARANTEED
    ];

    message Recovery
    {
        optional bool recover_at_final_goal = 1
            [default = true, (jaia.field).rest_api.presence = GUARANTEED];
        optional GeographicCoordinate location = 2
            [(jaia.field).rest_api.presence = GUARANTEED];
    }
    optional Recovery recovery = 4
        [(jaia.field).rest_api.presence = GUARANTEED];

    optional Speeds speeds = 5 [(jaia.field).rest_api.presence = GUARANTEED];
    optional BottomDepthSafetyParams bottom_depth_safety_params = 6
        [(jaia.field).rest_api.presence = GUARANTEED];
    optional uint32 fragment_index = 7 [(dccl.field) = { min: 0 max: 7 }];
    optional uint32 expected_fragments = 8 [(dccl.field) = { min: 1 max: 8 }];

    message TrailParam
    {
        option (dccl.msg) = {
            unit_system: "si"
        };

        optional int32 contact = 1
            [default = 0, (dccl.field) = { min: 0, max: 7 }];

        optional double angle = 2 [
            default = 180,
            (dccl.field) = {
                min: 0
                max: 360
                precision: 0
                units {
                    derived_dimensions: "plane_angle"
                    system: "angle::degree"
                }
            }
        ];
        optional bool angle_relative = 3 [default = true];
        optional double range = 4 [
            default = 50,
            (dccl.field) = {
                min: 0
                max: 500
                precision: 0
                units: { derived_dimensions: "length" }
            }
        ];
    }

    oneof movement_params
    {
        TrailParam trail = 10;
    }

    optional uint32 repeats = 9 [
        default = 1,
        (jaia.field).rest_api.presence = GUARANTEED,
        (dccl.field) = { min: 1 max: 100 }
    ];

}

message IvPBehaviorUpdate
{
    message TransitUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };
        required bool active = 1;

        optional double x = 2
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double y = 3
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double speed = 4 [
            (dccl.field).units = { base_dimensions: "LT^-1" }
        ];  // meters/second

        optional int32 slip_radius = 5;
    }

    message StationkeepUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };

        required bool active = 1;

        optional double x = 2
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double y = 3
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double outer_speed = 4 [
            (dccl.field).units = { base_dimensions: "LT^-1" }
        ];  // meters/second
        optional double transit_speed = 5 [
            (dccl.field).units = { base_dimensions: "LT^-1" }
        ];  // meters/second
        optional bool center_activate = 6 [default = false];
    }

    message ConstantHeadingUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };

        required bool active = 1;

        optional double heading = 2 [(dccl.field) = {
            min: 0
            max: 360
            precision: 0
            units { derived_dimensions: "plane_angle" system: "angle::degree" }
        }];
    }

    message ConstantSpeedUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };

        required bool active = 1;

        optional double speed = 2 [
            (dccl.field).units = { base_dimensions: "LT^-1" }
        ];  // meters/second
    }

    message TrailUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };

        required bool active = 1;

        optional MissionPlan.TrailParam param = 2;
    }

    message ContactUpdate
    {
        // unit dimensions must match those used by MOOS-IvP
        option (dccl.msg) = {
            unit_system: "si"
        };
        optional int32 contact = 1;
        optional double x = 2
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double y = 3
            [(dccl.field).units = { base_dimensions: "L" }];  // meters
        optional double speed = 4 [
            (dccl.field).units = { base_dimensions: "LT^-1" }
        ];  // meters/second
        optional double heading_or_cog = 5 [(dccl.field).units = {
            derived_dimensions: "plane_angle"
            system: "angle::degree"
        }];  // degrees
    }

    oneof behavior
    {
        TransitUpdate transit = 1;
        StationkeepUpdate stationkeep = 2;
        ConstantHeadingUpdate constantHeading = 3;
        ConstantSpeedUpdate constantSpeed = 4;
        TrailUpdate trail = 5;
        ContactUpdate contact = 6;
    }
}

message IvPBehaviorReport
{
    message TransitReport
    {
        optional bool waypoint_reached = 1 [default = false];
    }

    oneof behavior
    {
        TransitReport transit = 1;
    }
}

message MissionTpvMeetsGpsReq
{
    option (dccl.msg) = {
        unit_system: "si"
    };

    optional goby.middleware.protobuf.gpsd.TimePositionVelocity tpv = 1;
}
