/*
    1000 Bots - Surf the Web as Googlebot

    Copyleft (C) 2020 !Mediengruppe Bitnik, connect@bitnik.org

    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 <https://www.gnu.org/licenses/>.

*/

"use strict";

const DEBUG = false;

// Use chrome or browser depending on the environment
const browser = chrome || browser;

// Custom user-agent to spoof Googlebot
const user_agent =
	"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
const target_urls = "*://*/*";

// Duration to display the injected HTML (in milliseconds)
const DISPLAY_DURATION = 8000; // Set to 8 seconds

// Initialize storage for duration
browser.storage.sync
	.set({ duration: DISPLAY_DURATION })
	.then(() => {
		if (DEBUG) console.log("Duration set to:", DISPLAY_DURATION);
	})
	.catch((error) => {
		console.error("Error setting duration:", error);
	});

// Set extension status to ON
function set_extension_status_ON() {
	browser.storage.sync
		.set({ status: 1, bannerInjected: false, debug: DEBUG })
		.then(() => {
			if (DEBUG) console.log("Extension status set to ON");
			return browser.action.setIcon({ path: "icon_ON_48.png" });
		})
		.then(() => {
			return browser.action.setTitle({
				title: "You are now surfing the web as a bot 🤖",
			});
		})
		.then(() => {
			// Start user-agent spoofing
			return startUserAgentSpoofing();
		})
		.then(() => {
			// Refresh all tabs after starting user-agent spoofing
			return refreshAllTabs();
		})
		.then(() => {
			// Inject the content script into all active tabs after refreshing
			return injectContentScript();
		})
		.catch((error) => {
			console.error("Error setting extension status ON:", error);
		});
}

// Set extension status to OFF
function set_extension_status_OFF() {
	browser.storage.sync
		.set({ status: 0 })
		.then(() => {
			if (DEBUG) console.log("Extension status set to OFF");
			return browser.action.setIcon({ path: "icon_OFF_48.png" });
		})
		.then(() => {
			return browser.action.setTitle({
				title: "Click here to refuse to be human 🤖",
			});
		})
		.then(() => {
			// Remove the content from all active tabs
			return removeInjectedContent();
		})
		.then(() => {
			// Stop user-agent spoofing
			return stopUserAgentSpoofing();
		})
		.then(() => {
			// Refresh all tabs before stopping the extension
			return refreshAllTabs();
		})
		.catch((error) => {
			console.error("Error setting extension status OFF:", error);
		});
}

// Toggle the icon between ON and OFF
function update_icon() {
	browser.storage.sync
		.get("status")
		.then((result) => {
			if (result.status === 0) {
				set_extension_status_ON();
			} else {
				set_extension_status_OFF();
			}
		})
		.catch((error) => {
			console.error("Error fetching extension status:", error);
		});
}

// Start user-agent spoofing
function startUserAgentSpoofing() {
	const rules = [
		{
			id: 1,
			priority: 1,
			action: {
				type: "modifyHeaders",
				requestHeaders: [
					{
						operation: "set",
						header: "User-Agent",
						value: user_agent,
					},
				],
			},
			condition: {
				urlFilter: target_urls,
				resourceTypes: ["main_frame"],
			},
		},
	];

	// Add the rules
	return browser.declarativeNetRequest
		.updateDynamicRules({
			addRules: rules,
			removeRuleIds: [],
		})
		.then(() => {
			if (DEBUG)
				return console.log(
					"User-Agent spoofing rules added successfully."
				);
		})
		.then(() => {})
		.catch((error) => {
			console.error("Error adding rules:", error);
		});
}

// Stop user-agent spoofing
function stopUserAgentSpoofing() {
	return browser.declarativeNetRequest
		.updateDynamicRules({
			removeRuleIds: [1],
		})
		.then(() => {
			if (DEBUG)
				console.log("User-Agent spoofing rules removed successfully.");
		})
		.then(() => {
			// Clear the bannerInjected flag when stopping the extension
			return browser.storage.sync.set({ bannerInjected: false });
		})
		.catch((error) => {
			console.error("Error removing rules:", error);
		});
}

// Function to refresh all active tabs
function refreshAllTabs() {
	return browser.tabs.query({}).then((tabs) => {
		tabs.forEach((tab) => {
			browser.tabs
				.reload(tab.id)
				.then(() => {
					if (DEBUG) console.log(`Refreshed tab: ${tab.id}`);
				})
				.catch((error) => {
					console.error(`Error refreshing tab ${tab.id}:`, error);
				});
		});
	});
}

// Inject the content.js script into all active tabs
function injectContentScript() {
	return browser.tabs
		.query({})
		.then((tabs) => {
			// Create an array of promises for each tab
			const promises = tabs.map((tab) => {
				// Check if the URL is not something like chrome:// or about:// etc.
				if (tab.url.startsWith("https://")) {
					return browser.scripting
						.executeScript({
							target: { tabId: tab.id },
							files: ["content.js"],
						})
						.then(() => {
							if (DEBUG)
								console.log(
									`Content script injected into tab ${tab.id}`
								);

							// Use a hardcoded duration for removal
							const duration = 80000; // 8 seconds or whatever you need

							// Set a timeout to remove the content after the hardcoded duration
							setTimeout(() => {
								browser.storage.sync.set({
									bannerInjected: true,
								});
								if (DEBUG)
									console.log(
										"Duration expired. Removing content."
									);
								removeInjectedContent(); // Ensure this is defined
							}, duration);
						})
						.catch((error) => {
							console.error(
								`Error injecting content script into tab ${tab.id}:`,
								error
							);
						});
				} else {
					if (DEBUG)
						console.log(
							`Skipped injecting content script into tab ${tab.id} (chrome://, about:// URL or similar)`
						);
					return Promise.resolve(); // Return resolved promise for skipped tabs
				}
			});

			// Return a promise that resolves when all injections are complete
			return Promise.all(promises);
		})
		.then(() => {
			if (DEBUG)
				console.log("All scripts injected and removal timers set.");
		})
		.catch((error) => {
			console.error("Error querying tabs:", error);
		});
}

// Remove the content from all active tabs
function removeInjectedContent() {
	return browser.tabs
		.query({})
		.then((tabs) => {
			tabs.forEach((tab) => {
				if (tab.url.startsWith("https://")) {
					browser.scripting
						.executeScript({
							target: { tabId: tab.id },
							function: () => {
								const banner =
									document.querySelector(".extension-banner");
								if (banner && banner.parentNode) {
									banner.parentNode.removeChild(banner);
								}
							},
						})
						.then(() => {
							if (DEBUG)
								console.log(
									`Removed injected content from tab ${tab.id}`
								);
						})
						.catch((error) => {
							console.error(
								`Error removing injected content from tab ${tab.id}:`,
								error
							);
						});
				} else {
					if (DEBUG)
						console.log(
							`Skipped removing injected content from tab ${tab.id} (chrome://, about:// URL or similar)`
						);
				}
			});
		})
		.catch((error) => {
			console.error(
				"Error querying tabs for injected content removal:",
				error
			);
		});
}

// Event listeners for Manifest v3 Service Worker
browser.runtime.onInstalled.addListener(() => {
	set_extension_status_OFF(); // Set status to OFF on installation/startup
});

// Handle browser action clicks to toggle status
browser.action.onClicked.addListener(update_icon);
