//
//  ContentView.swift
//  v-browser
//
//  Created by Du Qingjie on 2024/09/08.
//

import SwiftUI
import WebKit
import AppKit

// WebPage structure
class WebPage: NSObject, ObservableObject, Identifiable, WKNavigationDelegate, WKUIDelegate {
    let id = UUID()
    var url: String
    var title: String
    var summary: String
    var wkWebView: WKWebView?
    var view: ContentView?
    
    @Published var canGoBack = false
    @Published var canGoForward = false
    @Published var favicon: Image?
    @Published var showCloseIcon = false
    
    init(view: ContentView, url: String, title: String, summary: String) {
        self.view = view
        self.url = url
        self.title = title
        self.summary = summary
        super.init()
        self.wkWebView = WebKit.WKWebView()
        self.wkWebView?.navigationDelegate = self
        self.wkWebView?.uiDelegate = self
        if let url = URL(string: url) {
            let request = URLRequest(url: url)
            self.wkWebView?.load(request)
            self.loadFavicon(for: url)
        }
    }
    
    func loadFavicon(for url: URL) {
        let faviconURL = url.appendingPathComponent("favicon.ico")
        
        URLSession.shared.dataTask(with: faviconURL) { data, response, error in
            if let data = data, let nsImage = NSImage(data: data) {
                DispatchQueue.main.async {
                    self.favicon = Image(nsImage: nsImage) // Set the fetched favicon
                }
            } else {
                DispatchQueue.main.async {
                    // Favicon not found, load the app icon instead
                    self.favicon = Image(nsImage: NSApp.applicationIconImage)
                }
            }
        }.resume()
    }
    
    func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
            if let url = navigationAction.request.url {
                // Instead of creating a new web view, loaod the URL in the current web view
                webView.load(URLRequest(url: url))
                canGoBack = true
            }
            return nil  // Return nil to prevent creating a new window
        }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        DispatchQueue.main.async {
            self.canGoBack = webView.canGoBack
            self.canGoForward = webView.canGoForward
            self.url = webView.url?.absoluteString ?? ""
            self.loadFavicon(for: URL(string: self.url)!)
            self.objectWillChange.send() // Notify SwiftUI that a change occurred
            let cur = self.view?.selectedTab
            self.view?.selectedTab = nil
            self.view?.selectedTab = cur
        }
    }
}

struct WebViewWrapper: NSViewRepresentable {
    var webView: WKWebView

    func makeNSView(context: Context) -> WKWebView {
        return webView
    }

    func updateNSView(_ nsView: WKWebView, context: Context) {
        // No need to update, as the WKWebView is already initialized and managed by WebPage
    }
}

struct ContentView: View {
    @State private var tabs: [WebPage] = [
        //WebPage(url: "https://amipro.me", title: "amiPro", summary: "Search the web"),
        //WebPage(url: "https://apple.com", title: "Apple", summary: "Apple's official website.")
    ]
    @State public var selectedTab: WebPage? = nil
    @State private var browsingHistory: [WebPage] = []
    @State private var currentURL: String = ""
    @State private var leftPanelWidth: CGFloat = 200
    @State private var rightPanelWidth: CGFloat = 200
    @State private var lastDragLocationX: CGFloat = -1000000
    
    @State private var curHoverTab: WebPage?
    
    var body: some View {
        VStack {
            // Address bar and navigation buttons
            HStack {
                TextField("Enter URL or Ask AI", text: $currentURL)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                    .frame(maxWidth: .infinity)
                    .onSubmit {
                        openTab(urlTxt: currentURL)
                    }
                Button("Go") {
                    openTab(urlTxt: currentURL)
                }
                .padding(.leading, 5)
                
                Button("<") {
                    goBack()
                }
                .disabled(!(selectedTab?.canGoBack ?? false))
                
                Button(">") {
                    goForward()
                }
                .disabled(!(selectedTab?.canGoForward ?? false))
            }
            .padding()

            // Main body with draggable panels
            HStack(spacing: 0) {
                // Left panel (Tabs)
                VStack(spacing: 0) {
                    ScrollView {
                        ForEach(tabs) { tab in
                            HStack{
                                if tab.showCloseIcon {
                                    Image(systemName: "xmark.circle.fill") // Show close icon on hover
                                        .onTapGesture {
                                            closeTab(tab: tab)
                                        }
                                        .frame(width: 16, height: 16)
                                } else {
                                    tab.favicon?.resizable()
                                        .frame(width: 16, height: 16) // Show favicon
                                }
                                Button(action: { selectedTab = tab }) {
                                    Text(tab.title)
                                        .lineLimit(1)
                                        .truncationMode(.tail)
                                        .padding(6)
                                        .frame(width: leftPanelWidth - 32, alignment: .leading)
                                        .foregroundColor(tab == selectedTab ? Color.primary : Color.secondary)  // Text color
                                        .background(
                                            tab == selectedTab ? Color.accentColor.opacity(0.2) : Color.gray.opacity(0.1) // Adaptive background color
                                        )
                                }.buttonStyle(PlainButtonStyle()).frame(height: 21)
                            }.onHover { hovering in
                                if nil != curHoverTab{
                                    curHoverTab?.showCloseIcon = false
                                }
                                curHoverTab = tab
                                tab.showCloseIcon = hovering // Toggle between favicon and close icon
                                let cur = self.selectedTab
                                self.selectedTab = nil
                                self.selectedTab = cur
                            }
                        }
                    }
                    .frame(width: leftPanelWidth)
                    .background(Color.gray.opacity(0.1))
                    .gesture(DragGesture()
                        .onChanged { value in
                            let chg = (-1000000 == lastDragLocationX) ? value.location.x-value.startLocation.x: value.location.x-lastDragLocationX
                            lastDragLocationX = value.location.x
                            let newWidth = leftPanelWidth + chg //value.translation.width
                            if newWidth > 30 && newWidth < 600 {
                                leftPanelWidth = newWidth
                            }
                        }
                        .onEnded { value in
                            lastDragLocationX = -1000000
                        }
                    )
                }
                
                // Draggable divider between tabs and WebView
                Rectangle()
                    .frame(width: 1)
                    .foregroundColor(.gray)
                    .gesture(DragGesture()
                        .onChanged { value in
                            let chg = (-1000000 == lastDragLocationX) ? value.location.x-value.startLocation.x: value.location.x-lastDragLocationX
                            lastDragLocationX = value.location.x
                            let newWidth = leftPanelWidth + chg //value.translation.width
                            if newWidth > 30 && newWidth < 600 {
                                leftPanelWidth = newWidth
                            }
                        }
                        .onEnded{value in
                            lastDragLocationX = -1000000
                        }
                    )
                    .onHover { hovering in
                        if hovering {
                            NSCursor.resizeLeftRight.set()  // Set cursor to left-right resize
                        } else {
                            NSCursor.arrow.set()  // Reset cursor when not hovering
                        }
                    }

                // Center panel (WebView or AI result)
                VStack {
                    if let selectedTab = selectedTab, let webView = selectedTab.wkWebView {
                            WebViewWrapper(webView: webView)
                                .id(selectedTab.id)  // Force SwiftUI to reinitialize when the tab changes
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                        } else {
                            Text("No tab selected")
                                .font(.headline)
                                .frame(maxWidth: .infinity, maxHeight: .infinity)
                        }
                }
                
                Rectangle()
                    .frame(width: 1)
                    .foregroundColor(.gray)
                    .gesture(DragGesture()
                        .onChanged { value in
                            let newWidth = rightPanelWidth - value.translation.width
                            if newWidth > 100 && newWidth < 600 {
                                rightPanelWidth = newWidth
                            }
                        }
                    )
                    .onHover { hovering in
                        if hovering {
                            NSCursor.resizeLeftRight.set()  // Set cursor to left-right resize
                        } else {
                            NSCursor.arrow.set()  // Reset cursor when not hovering
                        }
                    }

                // Right panel (Browsing History)
                VStack {
                    ScrollView {
                        ForEach(browsingHistory) { page in
                            Text(page.title)
                                .padding(10)
                                .frame(maxWidth: .infinity, alignment: .leading)
                                .background(page == selectedTab ? Color.blue.opacity(0.2) : Color.clear)
                                .cornerRadius(5)
                                .onTapGesture {
                                    selectedTab = page
                                }
                        }
                    }
                    .frame(width: rightPanelWidth)
                    .background(Color.gray.opacity(0.1))
                    .gesture(DragGesture()
                        .onChanged { value in
                            let newWidth = rightPanelWidth - value.translation.width
                            if newWidth > 100 && newWidth < 400 {
                                rightPanelWidth = newWidth
                            }
                        }
                    )
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            
            // Bottom bar with system status
            HStack {
                Text("System Status: OK")
                    .font(.footnote)
                Spacer()
            }
            .padding([.leading, .bottom])
            .background(Color.gray.opacity(0.1))
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .onAppear {
            // Automatically open a tab when the view appears
            openTab(urlTxt: "https://amipro.me")
        }
    }
    
    func isValidURL(_ urlString: String) -> Bool {
        if let url = URL(string: urlString) {
            // Check if the URL has a valid scheme (http, https, etc.)
            return ((url.scheme) != nil)
        }
        return false
    }
    
    func openTab(urlTxt: String){
        if isValidURL(urlTxt){
            createTab(url: URL(string: urlTxt)?.absoluteString ?? "", title: "Loading...", summary: "Loading...")
        }else if isValidURL("https://"+urlTxt){
            createTab(url: URL(string: "https://"+urlTxt)?.absoluteString ?? "", title: "Loading...", summary: "Loading...")
        }else{
            createTab(url: "https://www.google.com/search?q="+urlTxt.replacingOccurrences(of: " ", with: "+"), title: "Loading...", summary: "Loading...")
            //try to ask AI
        }
    }

    func createTab(url: String, title: String, summary: String) {
        let newPage = WebPage(view: self, url: url, title: title, summary: summary)
        tabs.append(newPage)
        selectedTab = newPage
    }

    func closeTab(tab: WebPage) {
        if let index = tabs.firstIndex(where: { $0.id == tab.id }) {
            tabs.remove(at: index)
            if selectedTab?.id == tab.id {
                selectedTab = tabs.last
            }
        }
    }
    
    func goBack() {
        if let selectedTab = selectedTab, selectedTab.canGoBack == true {
            selectedTab.wkWebView?.goBack()
            selectedTab.canGoForward = true
        }
    }
    
    func goForward() {
        if let selectedTab = selectedTab, selectedTab.canGoForward == true {
            selectedTab.wkWebView?.goForward()
            selectedTab.canGoBack = true
        }
    }
}

/*Preview {
    ContentView()
}*/
