/*
* Copyright (c) 2016 bitseater (https://github.com/bitseater/meteo)
*
* 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 2 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authored by: bitseater <bitseater@gmail.com>
*/
namespace  Meteo.Widgets {

    public class City : Gtk.Box {

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

        struct Mycity {
            double lat;
            double 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 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 (double), typeof (double), 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.activate.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 {
                    citylist.clear ();
                    window.ticket.reveal_child = false;
                    var busqueda = new Geocode.Forward.for_string (cityentry.get_text ());
                    try {
                        var cities = busqueda.search ();
                        Gtk.TreeIter iter;
                        foreach (var city in cities) {
                            var tipo = city.place_type;
                            var town = city.town;
                            var state = city.state;
                            var country = city.country_code;
                            var lat = city.location.latitude;
                            var lon = city.location.longitude;
                            if (tipo == Geocode.PlaceType.TOWN && town != null) {
                                citylist.append (out iter);
                                citylist.set (iter, 0, lat, 1, lon,
                                                    2, country, 3, state, 4, town);
                            }
                        }
                    } 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 uri1 = Constants.OWM_API_ADDR + "weather?lat=";
                var uri2 = "&type=like&APPID=" + setting.get_string ("apiid");
                var uri = uri1 + city.lat.to_string () + "&lon=" + city.lon.to_string () + uri2;
                setting.set_string ("idplace", update_id (uri));
                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 uri) {
            var session = new Soup.Session ();
            var message = new Soup.Message ("GET", uri);
            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;
        }
    }
}
