/****************************************************************************
**
** Copyright (C) 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
** Copyright (C) 2020-2021 General Magic B.V., info@generalmagic.com
**
** BSD License Usage
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of Klarälvdalens Datakonsult AB nor the names of
**     its contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
****************************************************************************/

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

// This example shows how to manually interactively select 2 or more
// landmarks, or waypoints, and then center the group of waypoints
// in the viewport such that their enclosing bounding box fills the
// viewport vertically or horizontally or both.
// Left click and hold anywhere on the map, and a list of nearby
// landmarks is displayed. Then left click on one of the options.
// Repeat for a second landmark, and then click center on landmark list.

// This code between the start and end markers is copied into the doc.

// setup codesnippet starts here
//! [LandmarkList plumbing]

import QtQuick.Window 2.12
import GeneralMagic 2.0

Window {

    visible: true
    width: 640
    height: 480
    title: qsTr("Interactive CenterOnLandmarkList Example")

    property var updater: ServicesManager.contentUpdater(ContentItem.Type.RoadMap)
    Component.onCompleted: {

        //! [Set token safely]
        ServicesManager.settings.token = __my_secret_token;
        //! [Set token safely]

        ServicesManager.settings.allowInternetConnection = true; // enable connection to online services

        updater.autoApplyWhenReady = true;
        updater.update();
    }

    //! [LandmarkList plumbing]
    // setup codesnippet ends here

    // reverse geocoding codesnippet starts here
    //! [LandmarkList ReverseGeocoding]

    SearchService {

        // Reverse geocoding takes as input a location on the map (lon,lat coordinates),
        // in this case, interactively selected by the user, and gives as output a list
        // of points of interest located near the selected position, 3 items in this example.

        id: reverseGeocoding
        searchMapPOIs: true
        searchAddresses: true
        limit: 10
        thresholdDistance: 500

        // The list of 3 points of interest located near the selected position
        // is shown here in a popup, giving the user the option to select one of them
        // to be added as a waypoint for a route, or simply click outside the popup to close it.

        onSearchCompleted: addWaypointPopup.open()
    }

    Popup {

        // This shows the results of the reverse geocoding in a popup.

        id: addWaypointPopup
        modal: true
        focus: true
        closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
        width: 300
        height: 200

        ListView {

            id: searchList
            anchors.fill: parent
            anchors.margins: 1
            clip: true
            model: reverseGeocoding

            delegate: Item {

                height: row.height

                RowLayout {

                    id: row

                    IconView {
                        iconSource: landmark.icon
                        Layout.maximumHeight: row.height
                        Layout.maximumWidth: row.height
                        width: height
                        height: row.height
                    }
                    ColumnLayout {

                        Layout.fillHeight: true
                        Layout.fillWidth: true

                        Text {
                            Layout.fillWidth: true
                            text: landmark.name + " (" + distance(landmark.coordinates.distance(reverseGeocoding.coordinates)) + ")"
                            wrapMode: Text.WrapAnywhere
                        }
                        Text {
                            Layout.fillWidth: true
                            text: landmark.description
                            font.italic: true
                            wrapMode: Text.WrapAnywhere
                        }
                    }
                    TapHandler {
                        target: row
                        onTapped: {

                            // This adds a waypoint to the route by selecting
                            // an item from the popup list of reverse geocoding results.

                            routingWaypoints.append(landmark)
                            addWaypointPopup.close()
                        }
                    }
                }
            }
        }
    }

    //! [LandmarkList ReverseGeocoding]
    // reverse geocoding codesnippet ends here

    // routing setup codesnippet begins here
    //! [LandmarkList routing]

    LandmarkList {

        // This is the waypoint list for the route,
        // including the departure and destination.

        id: routingWaypoints
    }

    RoutingService {
        id: routingService
        type: Route.Type.Fastest
        transportMode: Route.TransportMode.Car

        // The list of waypoints is made available to the routing service.

        waypoints: routingWaypoints
        onFinished: {
            mapView.routeCollection.set(routeList);
            mapView.centerOnRouteList(routeList);
        }
    }

    //! [LandmarkList routing]
    // routing setup codesnippet ends here

    // interactive landmarklist codesnippet begins here
    //! [LandmarkList select]

    function distance(meters)
    {
        return meters >= 1000 ? (meters / 1000.).toFixed(3) + " Km" :  meters.toFixed(0) + " m";
    }

    //! [LandmarkList select]
    // interactive landmarklist codesnippet ends here

    // map view codesnippet starts here
    //! [LandmarkList mapView]

    MapView {
        id: mapView
        anchors.fill: parent
        viewAngle: 25
        cursorVisibility: false

        onRouteSelected: {
            routeCollection.mainRoute = route;
            centerOnRoute(route);
        }

    //! [LandmarkList mapView]
    // map view codesnippet ends here

    // interactive map waypoint codesnippet starts here
    //! [LandmarkList waypoints]

        Label {
            id: infoLabel
            anchors.top: parent.top
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Long press to add a waypoint"
        }
        CheckBox {
            id: useReverseGeocoding
            anchors.top: infoLabel.bottom
            anchors.horizontalCenter: parent.horizontalCenter

            checked: true
            text: "Show reverse geocoding list"
        }

        TapHandler {
            grabPermissions: PointerHandler.CanTakeOverFromAnything
            onLongPressed: {
                if (!useReverseGeocoding.checked) {

                    // This adds a waypoint to the route by long-tapping
                    // (tapping and holding for about a second)
                    // a given location directly on the map.
                    // First, create a landmark that can hold a route waypoint.

                    //Creates a landmark that is owned by the routingWaypoints, for efficiency.
                    //This is required because
                    //routingWaypoints.append(lmk);
                    //will clone the landmark unless the owner is the routingWaypoints list itself.

                    let lmk = ServicesManager.createLandmark(routingWaypoints);

                    // Next, add the map coordinates from the tap location to the waypoint.

                    lmk.coordinates = mapView.wgsForScreen(point.pressPosition);

                    // Finally, add the waypoint to the list from which the route is generated.

                    routingWaypoints.append(lmk);

                    console.log("Waypoint added #########");

                    return;
                }

                if (point.pressPosition.x + addWaypointPopup.width > mapView.width)
                    addWaypointPopup.x = point.pressPosition.x - addWaypointPopup.width;
                else
                    addWaypointPopup.x = point.pressPosition.x

                if (point.pressPosition.y + addWaypointPopup.height > mapView.height)
                    addWaypointPopup.y = point.pressPosition.y - addWaypointPopup.height;
                else
                    addWaypointPopup.y = point.pressPosition.y

                reverseGeocoding.coordinates = mapView.wgsForScreen(point.pressPosition);
                reverseGeocoding.search();
            }
        }

    //! [LandmarkList waypoints]
    // interactive map waypoint codesnippet ends here

        // The control buttons at the bottom.

        RowLayout {

            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            spacing: 20

            // compute routing codesnippet begins here
            //! [LandmarkList compute routing]

            Button {
                text: "Center on landmark list"
                enabled: ServicesManager.settings.connected && routingWaypoints.length > 1
                onClicked: {
                    //show landmarks on map as point markers
                    let marker = ServicesManager.createMarker();
                    for (let n = 0; n < routingWaypoints.length; n++) {
                        let lmkit = routingWaypoints.get(n)
                        marker.append(lmkit.coordinates);
                    }
                    let renderSettings = ServicesManager.createMarkerRenderSettings();
                    let list = mapView.markerCollection.getExtendedList(MarkerList.Type.Point);
                    list.append(marker, renderSettings);

                    //center on list of waypoints/landmarks
                    mapView.centerOnGeographicArea(routingWaypoints.boundingBox)

                    //center on route plotted from list of waypoints/landmarks
                    //you can uncomment the line below to treat the points as a route
                    //instead of a group of landmarks, and render the route centered:
                    //routingService.update()
                }
            }

            //! [LandmarkList compute routing]
            // compute routing codesnippet ends here

            Item {
                Layout.fillWidth: true
            }
            Button {
                enabled: routingWaypoints.length
                text: "Clear landmark list/waypoints"
                onClicked: {
                    routingWaypoints.clear();
                }
            }
        }

    // map view codesnippet closing parenthesis starts here
    //! [LandmarkList mapView end]
    }
    //! [LandmarkList mapView end]
    // map view codesnippet closing parenthesis ends here

// setup codesnippet closing parenthesis starts here
//! [LandmarkList plumbing end]
}
//! [LandmarkList plumbing end]
// setup codesnippet closing parenthesis ends here
