/*
* Copyright (c) 2017-2018 Carlos Suárez (https://gitlab.com/bitseater)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Carlos Suárez <bitseater@gmail.com>
*/
namespace  Meteo.Widgets {

    public class City : Gtk.Box {

        public Meteo.MainWindow window;
        private Meteo.Widgets.Header header;

        struct Mycity {
            string lat;
            string lon;
            string country;
            string state;
            string town;
        }

        public City (Meteo.MainWindow window, Meteo.Widgets.Header header) {
            orientation = Gtk.Orientation.VERTICAL;
            spacing = 5;

            this.window = window;
            this.header = header;
            window.set_titlebar (header);
            header.set_title ("");

            var search_line = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 5);
            pack_start (search_line, false, false, 5);

            var uri1 = "https://nominatim.openstreetmap.org/search?city=";
            var uri2 = "&format=json&addressdetails=1";

            var citylabel = new Gtk.Label (_("Search for new location") + ":");
            search_line.pack_start (citylabel, false, false, 5);
            var cityentry = new Gtk.Entry ();
            cityentry.max_length = 40;
            cityentry.primary_icon_name = "system-search-symbolic";
            cityentry.secondary_icon_name = "edit-clear-symbolic";
            search_line.pack_start (cityentry, true, true, 5);

            var cityview = new Gtk.TreeView ();
            cityview.expand = true;
            var citylist = new Gtk.ListStore (5, typeof (string), typeof (string), typeof (string), typeof (string), typeof(string));
            cityview.model = citylist;
            cityview.insert_column_with_attributes (-1, _("Lat"), new Gtk.CellRendererText (), "text", 0);
            cityview.insert_column_with_attributes (-1, _("Lon"), new Gtk.CellRendererText (), "text", 1);
            cityview.insert_column_with_attributes (-1, _("Country"), new Gtk.CellRendererText (), "text", 2);
            cityview.insert_column_with_attributes (-1, _("State"), new Gtk.CellRendererText (), "text", 3);
            cityview.insert_column_with_attributes (-1, _("Location"), new Gtk.CellRendererText (), "text", 4);
            var scroll = new Gtk.ScrolledWindow (null,null);
            scroll.hscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
            scroll.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC;
            scroll.add (cityview);

            cityentry.icon_press.connect ((pos, event) => {
                if (pos == Gtk.EntryIconPosition.SECONDARY) {
                    cityentry.set_text ("");
                    citylist.clear ();
                }
            });

            var overlay = new Gtk.Overlay ();
            pack_end (overlay, true, true, 0);
            overlay.add_overlay (scroll);

            cityentry.changed.connect (() => {
                if (cityentry.get_text_length () < 3) {
                    citylist.clear ();
                    window.ticket.set_text (_("At least of 3 characters are required!"));
                    window.ticket.reveal_child = true;
                } else {
                    string uri = "";
                    citylist.clear ();
                    window.ticket.reveal_child = false;
                    uri = uri1 + cityentry.get_text () + uri2;
                    var session = new Soup.Session ();
                    var message = new Soup.Message ("GET", uri);
                    message.request_headers.append ("User-Agent", "com.gitlab.bitseater.meteo");
                    session.send_message (message);
                    try {
                        var parser = new Json.Parser ();
                        parser.load_from_data ((string) message.response_body.flatten ().data, -1);
                        var root = parser.get_root ().get_array ();
                        if (root.get_length () > 0) {
                            int i;
                            for (i=0; i< root.get_length (); i++) {
                                var osmobj = root.get_object_element (i);
                                var osmlat = osmobj.get_string_member ("lat");
                                var osmlon = osmobj.get_string_member ("lon");
                                var address = osmobj.get_object_member ("address");
                                var osmname = "";
                                if (address.has_member ("city")) {
                                    osmname = address.get_string_member ("city");
                                } else if (address.has_member ("town")) {
                                    osmname = address.get_string_member ("town");
                                }
                                if (osmname != "") {
                                    var osmstate = "";
                                    if (address.has_member ("state")) {
                                        osmstate = address.get_string_member ("state");
                                    }
                                    var osmcountry = address.get_string_member ("country_code");
                                    Gtk.TreeIter iter;
                                    citylist.append (out iter);
                                    citylist.set (iter, 0, osmlat,
                                                        1, osmlon,
                                                        2, osmcountry.up (),
                                                        3, osmstate,
                                                        4, osmname);
                                }
                            }
                        }
                    } catch (Error error) {
                        window.ticket.set_text (_("No data"));
                        window.ticket.reveal_child = true;
                    }
                }
            });
            cityview.row_activated.connect (on_row_activated);
        }

        private static Mycity get_selection (Gtk.TreeModel model, Gtk.TreeIter iter) {
            var city = Mycity ();
            model.get (iter, 0, out city.lat, 1, out city.lon, 2, out city.country, 3, out city.state, 4, out city.town);
            return city;
        }

        private void on_row_activated (Gtk.TreeView cityview , Gtk.TreePath path, Gtk.TreeViewColumn column) {
            Gtk.TreeIter iter;
            if (cityview.model.get_iter (out iter, path)) {
                Mycity city = get_selection (cityview.model, iter);
                var setting = new Settings ("com.gitlab.bitseater.meteo");
                var url1 = Constants.OWM_API_ADDR + "weather?lat=";
                var url2 = "&type=like&APPID=" + setting.get_string ("apiid");
                var url = url1 + city.lat + "&lon=" + city.lon + url2;
                setting.set_string ("idplace", update_id (url));
                setting.set_string ("country", city.country);
                setting.set_string ("state", city.state);
                setting.set_string ("location", city.town);
                var current = new Meteo.Widgets.Current (window, header);
                window.change_view (current);
                window.show_all ();
            }
        }

        private static string update_id (string url) {
            var session = new Soup.Session ();
            var message = new Soup.Message ("GET", url);
            session.send_message (message);
            string id = "";
            try {
                var parser = new Json.Parser ();
                parser.load_from_data ((string) message.response_body.flatten ().data, -1);
                var root = parser.get_root ().get_object ();
                id = root.get_int_member ("id").to_string();
            } catch (Error e) {
                debug (e.message);
            }
            return id;
        }
    }
}
