//
// Copyright 2015-2021 by Garmin Ltd. or its subsidiaries.
// Subject to Garmin SDK License Agreement and Wearables
// Application Developer Agreement.
//

import Toybox.Application;
import Toybox.Application.Storage;
import Toybox.Graphics;
import Toybox.Lang;
import Toybox.Timer;
import Toybox.WatchUi;

var menu_dec = null;
var menu_unit = null;

function do_menu(where)
{

    C.logger("onMenu:" + where);
    var menu2 = new Menu2({:title => "Settings"});
    menu2.addItem(new MenuItem("Position",      null, C.MENU_POS, null));
    menu2.addItem(new MenuItem("Units",         null, C.MENU_UNITS, null));
    menu2.addItem(new MenuItem("Declination",   null, C.MENU_DECL, null));
    menu2.addItem(new MenuItem("Ceiling",       null, C.MENU_CEILING, null));
    WatchUi.pushView(menu2, new MenuDelegate(), WatchUi.SLIDE_UP);
    return true;
}

class MenuDelegate extends WatchUi.Menu2InputDelegate
{

public function initialize()
{
    C.logger("initialize:MenuDelegate");
    Menu2InputDelegate.initialize();
}

//
//  This routine handles all touch events for the settings pages
//  As long as every menu item has a unique id then this should
//  cause no problems.
//
public function onSelect(item as MenuItem) as Void
{
    var t, tt;
    // C.logger("onSelect:MenuDelegate");
    var menu2 = null;
    var n = item.getId();
    var id = (n as Number).toNumber();
    switch (id) {

    case C.MENU_IGNORE:
        break;

    case C.MENU_POS:
        menu2 = new Menu2({:title => "Position"});
        menu2.addItem(new MenuItem(C.n2str(C.lat, 2), "latitude", C.MENU_IGNORE, null));
        menu2.addItem(new MenuItem(C.n2str(C.lon, 2), "longitude", C.MENU_IGNORE, null));
        WatchUi.pushView(menu2, new MenuDelegate(), WatchUi.SLIDE_UP);
        break;

    case C.MENU_UNITS:
        menu_unit = new Menu2({:title => "Units"});
        menu_unit.addItem(new ToggleMenuItem("Imperial", null, C.MENU_UNIT_IMP, (C.units == C.UNITS_IMPERIAL), {}));
        menu_unit.addItem(new ToggleMenuItem("Metric", null, C.MENU_UNIT_METRIC, (C.units == C.UNITS_METRIC), {}));
        WatchUi.pushView(menu_unit, new MenuDelegate(), WatchUi.SLIDE_UP);
        break;

    case C.MENU_UNIT_IMP:
        t = item as ToggleMenuItem;
        if ((C.units == C.UNITS_IMPERIAL) && !t.isEnabled()) {
            t.setEnabled(true);
            break;
        }
        tt = menu_unit.getItem(menu_unit.findItemById(C.MENU_UNIT_METRIC));
        set_units(t, t.isEnabled(), tt, !t.isEnabled(), C.UNITS_IMPERIAL);
        break;

    case C.MENU_UNIT_METRIC:
        t = item as ToggleMenuItem;
        if ((C.units == C.UNITS_METRIC) && !t.isEnabled()) {
            t.setEnabled(true);
            break;
        }
        tt = menu_unit.getItem(menu_unit.findItemById(C.MENU_UNIT_IMP));
        set_units(t, t.isEnabled(), tt, !t.isEnabled(), C.UNITS_METRIC);
        break;

    case C.MENU_DECL:
        menu_dec = new Menu2({:title => "Mag Dec"});
        menu_dec.addItem(new ToggleMenuItem("Auto", "use GPS", C.MENU_DECL_AUTO, C.mag_auto, null));
        menu_dec.addItem(new MenuItem(C.n2str(C.mag_value, 2), "Set value", C.MENU_DECL_SET, null));
        set_decl(menu_dec.getItem(menu_dec.findItemById(C.MENU_DECL_SET)));
        WatchUi.pushView(menu_dec, new MenuDelegate(), WatchUi.SLIDE_UP);
        break;

    case C.MENU_DECL_AUTO:
        t = item as ToggleMenuItem;
        C.mag_auto = t.isEnabled();
        Application.getApp().setProperty("mag_auto", C.mag_auto);
        set_decl(menu_dec.getItem(menu_dec.findItemById(C.MENU_DECL_SET)));
        break;

    case C.MENU_CEILING:
        menu2 = new Menu2({:title => "Ceiling (ft)"});
        menu2.addItem(new MenuItem(C.n2str(C.ceiling, 0), "Change in Connect iQ", C.MENU_IGNORE, null));
        WatchUi.pushView(menu2, new MenuDelegate(), WatchUi.SLIDE_UP);
        break;

    }
}

public function onBack() as Void
{
    C.logger("onBack:MenuDelegate");
    popView(WatchUi.SLIDE_DOWN);
}

function set_units(ti, ti_e, tm, tm_e, u)
{

    ti.setEnabled(ti_e);
    tm.setEnabled(tm_e);
    C.units = u;
    Application.getApp().setProperty("units", u);
}

function set_decl(item)
{

    if (C.mag_auto) {
        item.setLabel(C.n2str(C.mag_gps, 1));
        item.setSubLabel("GPS set");
    } else {
        item.setLabel(C.n2str(C.mag_value, 1));
        item.setSubLabel("Change in Connect IQ");
    }
}

}

//! Initial view
class AmbitView extends WatchUi.View
{

private var compass;
private var sp_meter;
private var alt_meter;

//! Constructor
public function initialize(type)
{

    C.logger("view:initialize()");
    View.initialize();
    C.meter_type = type;
    C.mag_gps = Storage.getValue("mag_gps");
}

function onLayout(dc)
{

    C.logger("view:onLayout()");

    C.cx = dc.getWidth() / 2;
    C.cy = dc.getHeight() / 2;
    C.radius = (C.cx > C.cy) ? C.cy : C.cx;
    C.logger("radius:" + C.radius);

    var r10 = C.radius * 0.10;
    var tw = 2;     // tick width
    compass = new Compass("Compass",  C.radius, 10, r10, tw, C.WHITE);
    sp_meter =  new Meter("Speed",    C.radius, 10, r10, tw, 2, C.WHITE);
    alt_meter = new Meter("Altitude", C.radius, 10, r10, tw, 3, C.WHITE);
}

function onShow() as Void
{

    C.logger("view:onShow()");
    C.settings();
}

//! Update the view
//! @param dc Device context
public function onUpdate(dc as Dc)
{

    //C.logger("view:onUpdate()");

    dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK);
    dc.clear();
    dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);

    switch (C.meter_type) {

    case C.METER_COMPASS:
        compass.show(dc, C.get_heading());
        break;

    case C.METER_SPEED:
        sp_meter.show(dc, C.get_speed(C.speed));
        break;

    case C.METER_ALT:
        alt_meter.show(dc, C.get_alt(C.alt));
        break;

    }
}

}

//! Input handler for the progress bar
class ProgressDelegate extends WatchUi.BehaviorDelegate
{

private var _callback as Method() as Void;

//! Constructor
//! @param callback Callback function
public function initialize(callback as Method() as Void)
{

    C.logger("progress:onInitialize()");
    BehaviorDelegate.initialize();
    _callback = callback;
}

public function onMenu() as Boolean
{

    return do_menu("Progress");
}

//! Handle back behavior
//! @return true if handled, false otherwise
public function onBack() as Boolean
{

    C.logger("progress:onBack()");
    _callback.invoke();
    return true;
}

}

//! Creates and updates the progress bar
class AmbitDelegate extends WatchUi.BehaviorDelegate
{
private var view_idx as Number;

//! Constructor
public function initialize(idx)
{

    C.logger("input:onInitialize()");
    BehaviorDelegate.initialize();
    view_idx = idx;
}

public function onMenu() as Boolean
{

    return do_menu("Ambit");
}

public function onNextPage() as Boolean {
    C.logger("input:onNextPage()");
    var nextPage = (view_idx + 1) % C.NUM_VIEWS;
    var view = new AmbitView(nextPage);
    var delegate = new AmbitDelegate(nextPage);
    WatchUi.switchToView(view, delegate, WatchUi.SLIDE_RIGHT);

    return true;
}

public function onPreviousPage() as Boolean {
    C.logger("input:onPreviousPage()");
    var nextPage = (view_idx + C.NUM_VIEWS - 1) % C.NUM_VIEWS;
    var view = new AmbitView(nextPage);
    var delegate = new AmbitDelegate(nextPage);
    WatchUi.switchToView(view, delegate, WatchUi.SLIDE_LEFT);

    return true;
}

//! On a select event, create a progress bar
//! @return true if handled, false otherwise
public function onSelect() as Boolean
{

    C.logger("input:onSelect() = " + C.meter_type);
    C.meter_select(C.meter_type);
    return true;
}

}

//! Input handler for the main looping views
class AmbitViewLoopDelegate extends WatchUi.BehaviorDelegate
{
private var _index as Number;

//! Constructor
//! @param index The current page index
public function initialize(index as Number)
{

    C.logger("loop:initialize()");
    BehaviorDelegate.initialize();
    _index = index;
}

public function onMenu() as Boolean
{

    return do_menu("AmbitViewLoop");
}

//! On select behavior show the detail view
//! @return true if handled, false otherwise
public function onSelect() as Boolean
{

    C.logger("loop:onSelect() = " + C.meter_type);
    C.meter_select(C.meter_type);
    WatchUi.requestUpdate();
    return true;
}

}
