// Try installed path first, fall back to local development path
private const string INSTALLED_CONFIG_PATH = "/usr/share/quick-setup/page_config.json";
private const string DEV_CONFIG_PATH = "data/page_config.json";
private const string DEBUG_PAGE_CONFIG_JSON = """
{
  "main": {
    "pages": [
      "welcome",
      "drivers-pre-wifi",
      "network",
      "drivers-post-wifi",
      "installing-apps",
      "webbrowser",
      "apps",
      "donate",
      "explore"
    ]
  }
}""";

namespace QuickSetup {
    public class QuickSetupWindow : Adw.ApplicationWindow {
        public Adw.NavigationView navigation_view;
        public List<string> page_names;
        public CategoryData? shared_web_browser_category = null;
        private QsConfig config;
        private GLib.Settings settings;
        public int current_page_index = 0;
        public bool allow_close = false;
        public bool driver_reboot_required = false;
        public bool driver_reboot_prompt_shown = false;
        public bool combine_driver_phases = false;
        public bool nvidia_driver_queued = false;
        private HashTable<string, QsPage> created_pages;
        private bool network_gate_active = false;

        public QuickSetupWindow(Adw.Application app) {
            Object(
                application: app,
                title: "Quick Setup"
            );

            // Allow debug sessions to force an in-code config.
            bool force_dev_config = Environment.get_variable("QUICK_SETUP_USE_DEV_CONFIG") == "1";

            if (force_dev_config) {
                this.config = new QsConfig.from_json_string(DEBUG_PAGE_CONFIG_JSON);
            } else {
                // Use installed config if it exists, otherwise use dev path
                string config_path = INSTALLED_CONFIG_PATH;
                if (!FileUtils.test(INSTALLED_CONFIG_PATH, FileTest.EXISTS)) {
                    config_path = DEV_CONFIG_PATH;
                }
                this.config = new QsConfig(config_path);
            }
            this.settings = new GLib.Settings("io.stillhq.quicksetup");
            this.created_pages = new HashTable<string, QsPage>(str_hash, str_equal);
            this.combine_driver_phases =
                NetworkMonitor.get_default().connectivity == NetworkConnectivity.FULL;

            this.navigation_view = new Adw.NavigationView();
            this.navigation_view.pop_on_escape = false;
            this.navigation_view.popped.connect((popped_page) => {this.page_went_back(popped_page);});
            this.set_content(this.navigation_view);

            // Parse config file pages:
            this.page_names = config.get_page_string_array("main", "pages");

            // print page names for debugging
            foreach (var page_name in this.page_names) {
                print("Page name: %s\n", page_name);
            }

            this.apply_resume_page();
            push_next_page();
        }

        public void set_resume_page(string page_id) {
            this.settings.set_string("resume-page", page_id);
        }

        public void ensure_browser_pinned() {
            if (this.shared_web_browser_category != null) {
                pin_checked_browsers(this.shared_web_browser_category.apps);
            }
            sync_browser_favorites();
        }

        private void apply_resume_page() {
            string resume_page_id = this.settings.get_string("resume-page");

            if (resume_page_id.strip() == "") {
                return;
            }

            for (int i = 0; i < (int) this.page_names.length(); i++) {
                if (this.page_names.nth_data(i) == resume_page_id) {
                    this.current_page_index = i;
                    break;
                }
            }

            this.settings.set_string("resume-page", "");
        }

        private QsPage get_or_create_page(string page_name) {
            var existing = this.created_pages.get(page_name);
            if (existing != null) {
                return existing;
            }
            
            PageContext page_context = {
                window: this,
                navigation_view: this.navigation_view,
                config: this.config
            };

            var page = get_page_from_id(page_name, page_context);
            if (page != null) {
                this.created_pages.set(page_name, page);
            }
            return page;
        }

        public void push_next_page() {
            if (this.network_gate_active) {
                var connectivity = NetworkMonitor.get_default().connectivity;
                if (connectivity != NetworkConnectivity.FULL) {
                    warning(
                        "Cannot continue past network setup without working internet (status: %s)",
                        connectivity.to_string()
                    );
                    return;
                }
                this.network_gate_active = false;
            }

            while (this.current_page_index < this.page_names.length()) {
                var page_name = this.page_names.nth_data(this.current_page_index);

                // When internet access was already available at startup, the
                // pre-WiFi page handles both driver phases on one screen.
                // Check this before constructing the page: driver pages begin
                // their asynchronous work when constructed, even if they are
                // never pushed into the navigation view.
                if (this.combine_driver_phases && page_name == "drivers-post-wifi") {
                    print("Skipping page %s (combined with pre-WiFi drivers)\n", page_name);
                    this.current_page_index++;
                    continue;
                }

                var page = get_or_create_page(page_name);
                if (page == null) {
                    this.current_page_index++;
                    continue;
                }
                
                // Found a page we can show
                print("Page name: %s\n", page_name);
                this.navigation_view.push(page);

                if (page_name == "network") {
                    this.network_gate_active = true;
                }

                if (this.current_page_index > 0) {
                    var last_page_name = this.page_names.nth_data(this.current_page_index - 1);
                    // Never construct a previous page just to read this flag.
                    // Constructors may schedule automatic navigation. A page
                    // absent from the cache was skipped or predates a resumed
                    // session, so there is no page to navigate back to.
                    var last_page = this.created_pages.get(last_page_name);
                    if (last_page != null) {
                        page.set_back_button(last_page.can_go_back_to);
                    } else {
                        page.set_back_button(false);
                    }
                }

                this.current_page_index++;
                return;
            }

            // No more pages - close the window
            print("No more pages to show\n");
            this.allow_close = true;
            this.close();
        }

        public void page_went_back(Adw.NavigationPage popped_page) {
            // Only decrement index if the popped page is part of the main sequence
            if (popped_page is QsPage) {
                var qs_page = (QsPage) popped_page;
                // Check if this page ID is in the main sequence
                if (this.page_names.find_custom(qs_page.page_id, strcmp) != null) {
                    this.current_page_index--;
                }
            }
        }
    }
}
