import tkinter as tk
from tkinter import messagebox
from tkinter import scrolledtext
import json

class NoteTakingApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Note Taking App")
        self.notes = {}
        self.current_note_index = None

        self.load_notes()

        self.note_listbox = tk.Listbox(root, width=50)
        self.note_listbox.pack(side=tk.LEFT, fill=tk.Y)

        self.note_listbox.bind("<<ListboxSelect>>", self.show_note)

        self.note_text = scrolledtext.ScrolledText(root, width=50, height=10, wrap=tk.WORD)
        self.note_text.pack(fill=tk.BOTH, expand=True)

        self.create_btn = tk.Button(root, text="Create Note", command=self.create_note)
        self.create_btn.pack(side=tk.TOP, pady=5)

        self.save_btn = tk.Button(root, text="Save Note", command=self.save_note)
        self.save_btn.pack(side=tk.TOP, pady=5)

        self.delete_btn = tk.Button(root, text="Delete Note", command=self.delete_note)
        self.delete_btn.pack(side=tk.TOP, pady=5)

        self.search_entry = tk.Entry(root)
        self.search_entry.pack(side=tk.TOP, pady=5)

        self.search_btn = tk.Button(root, text="Search", command=self.search_note)
        self.search_btn.pack(side=tk.TOP)

        self.display_notes()

    def load_notes(self):
        try:
            with open("notes.json", "r") as file:
                self.notes = json.load(file)
        except FileNotFoundError:
            self.notes = {}

    def save_notes(self):
        with open("notes.json", "w") as file:
            json.dump(self.notes, file)

    def display_notes(self):
        self.note_listbox.delete(0, tk.END)
        for title in self.notes.keys():
            self.note_listbox.insert(tk.END, title)

    def create_note(self):
        title = messagebox.askstring("Title", "Enter note title:")
        if title:
            self.notes[title] = ""
            self.display_notes()
            self.current_note_index = title
            self.note_text.delete(1.0, tk.END)

    def show_note(self, event):
        try:
            selected_note_index = self.note_listbox.curselection()[0]
            title = self.note_listbox.get(selected_note_index)
            self.current_note_index = title
            self.note_text.delete(1.0, tk.END)
            self.note_text.insert(tk.END, self.notes[title])
        except IndexError:
            pass

    def save_note(self):
        if self.current_note_index:
            self.notes[self.current_note_index] = self.note_text.get(1.0, tk.END)
            self.save_notes()
            messagebox.showinfo("Success", "Note saved successfully!")
        else:
            messagebox.showwarning("Warning", "No note selected!")

    def delete_note(self):
        if self.current_note_index:
            del self.notes[self.current_note_index]
            self.display_notes()
            self.note_text.delete(1.0, tk.END)
            self.save_notes()
            messagebox.showinfo("Success", "Note deleted successfully!")
            self.current_note_index = None
        else:
            messagebox.showwarning("Warning", "No note selected!")

    def search_note(self):
        query = self.search_entry.get()
        if query:
            found = False
            self.note_listbox.delete(0, tk.END)
            for title, content in self.notes.items():
                if query.lower() in title.lower() or query.lower() in content.lower():
                    self.note_listbox.insert(tk.END, title)
                    found = True
            if not found:
                messagebox.showinfo("Info", "No matching notes found.")
        else:
            self.display_notes()

if __name__ == "__main__":
    root = tk.Tk()
    app = NoteTakingApp(root)
    root.mainloop()
