File size: 23,083 Bytes
dc18f90
ca7d642
 
 
 
76ce326
c674fc7
 
 
3ec1f10
c674fc7
 
 
 
 
6fa3e37
76ce326
c674fc7
 
 
 
 
 
 
 
 
2396855
c674fc7
2396855
3f8a43e
c674fc7
3f8a43e
c674fc7
 
 
 
3f8a43e
c674fc7
 
 
 
 
 
3f8a43e
c674fc7
 
 
 
3f8a43e
c674fc7
3f8a43e
76ce326
 
 
 
 
 
 
 
9a17648
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
610d0de
9a17648
 
3ec1f10
 
9a17648
 
 
 
3ec1f10
 
9a17648
 
 
3ec1f10
9a17648
 
 
 
 
 
 
 
c674fc7
 
f84f799
 
 
 
 
 
 
 
 
 
 
c674fc7
 
f0b3a83
 
9dddb7c
f0b3a83
9dddb7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0b3a83
 
7a3a139
 
 
 
 
 
 
 
 
 
 
9a17648
5d7b3f0
7a3a139
 
9dddb7c
 
 
 
 
 
 
 
 
 
 
7a3a139
 
 
 
614185c
0c62990
7a3a139
 
5d7b3f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5c9b443
46c3b9c
 
 
 
 
 
5d7b3f0
 
5227530
9dddb7c
 
5227530
9dddb7c
 
5227530
9dddb7c
 
 
 
5227530
9dddb7c
5227530
9dddb7c
 
5227530
 
ed1b5fc
 
 
 
 
 
 
 
 
 
 
 
 
 
3c99815
5227530
cae2692
 
 
d18d80b
 
 
 
 
cae2692
d18d80b
 
cae2692
d18d80b
 
 
5d7b3f0
d18d80b
 
 
 
 
 
 
 
 
 
 
 
 
7ebcabb
d18d80b
7ebcabb
 
 
 
 
 
 
 
 
 
 
 
d18d80b
 
 
7ebcabb
 
 
d18d80b
 
 
7ebcabb
 
d18d80b
 
 
 
7ebcabb
d18d80b
7ebcabb
d18d80b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f0b3a83
 
5d7b3f0
7ebcabb
182b1e5
d154fde
d868a54
 
 
 
05e3623
d868a54
 
 
 
 
05e3623
d868a54
 
d154fde
d868a54
d154fde
 
 
f0b3a83
a3a7f0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
881217c
a3a7f0e
 
 
 
 
 
 
 
 
d7a884a
a3a7f0e
 
 
 
 
d7a884a
 
5e7868b
 
a3a7f0e
 
 
 
5e7868b
 
9de352b
 
807d76a
9de352b
d868a54
807d76a
 
9de352b
 
 
807d76a
 
9de352b
 
807d76a
9de352b
 
 
807d76a
 
9de352b
 
807d76a
d868a54
807d76a
 
 
9de352b
 
 
 
807d76a
 
9de352b
 
807d76a
 
 
 
 
 
d868a54
a3a7f0e
 
d868a54
38fe949
d7a884a
 
 
 
d868a54
a3a7f0e
d7a884a
 
 
 
 
 
 
6fa3e37
 
a3a7f0e
 
 
 
 
6fa3e37
a3a7f0e
 
5e7868b
 
d7a884a
 
a3a7f0e
5e7868b
6fa3e37
f0b3a83
 
89717b4
807d76a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89717b4
a5ea3fb
38fe949
a5ea3fb
 
 
 
 
 
 
 
 
a410f9f
 
 
2b4fccf
a5ea3fb
38fe949
89717b4
a410f9f
38fe949
 
 
 
89717b4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cae2692
 
 
 
89717b4
 
 
18cbbee
89717b4
 
 
cae2692
 
 
89717b4
 
cae2692
 
 
 
 
 
 
 
 
 
 
89717b4
 
 
cae2692
 
89717b4
 
 
 
 
 
 
 
 
 
 
d18d80b
89717b4
 
 
a3a7f0e
7a3a139
 
38fe949
18cbbee
 
 
 
 
 
7a3a139
18cbbee
 
 
 
 
 
 
 
 
f0b3a83
8f2ba3c
c76d922
 
8cc1d61
 
 
 
c76d922
 
 
 
 
 
 
 
 
 
 
 
 
f16988b
 
 
 
 
c76d922
 
27ffa1a
f16988b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
// Load data from JSON file
// window.speechSynthesis.onvoiceschanged = () => {
//     const voices = window.speechSynthesis.getVoices();
//     console.log('Available voices:', voices);
// };
document.addEventListener('DOMContentLoaded', function() {
  const token = localStorage.getItem('authToken');
  const userInfoDiv = document.getElementById('user-info');
  const loginLink = document.getElementById('login-link');
  const charchaButton = document.getElementById('charchaButton');
  
  if (token) {
    // Check token validity with backend
    fetch('https://thevera-botveradb.hf.space/validate_token', {
      method: 'GET',
        headers: {
        'Authorization': `Bearer ${token}`
      }
    })
    .then(response => response.json())
    .then(data => {
      // if (data.success) {
      if (data.message === "Token is valid!") {
        // Token is valid, extract user's email and display it
        const userObject = jwt_decode(token); // Decode the token to get user info
        const email = userObject.email; // Assuming the email is stored in the token
        const username = email.split('@')[0];
        // Display user information
        document.getElementById('user-name').innerText = username; // Display first name
        userInfoDiv.style.display = 'block'; // Show user info
        document.getElementById('logout-button').style.display = 'inline'; // Show logout button
        loginLink.style.display = 'none'; // Hide login link
      } else {
        // Token is invalid, clear invalid token
        localStorage.removeItem('authToken');
        console.log('Invalid token, user not logged in.');
        loginLink.style.display = 'inline'; // Show login link
      }
    })
    .catch(error => {
      console.error('Error:', error);
      // Handle the error (e.g., network issues)
      localStorage.removeItem('authToken'); // Clear token in case of error
      loginLink.style.display = 'inline'; // Show login link
    });
  } else {
    // No token found, show login link
    console.log('No token found, user not logged in.');
    loginLink.style.display = 'inline';
  }
  
  // Logout function
  const logoutButton = document.getElementById('logout-button');
  if (logoutButton) {
    logoutButton.onclick = function() {
      localStorage.removeItem('authToken'); // Clear token
      window.location.reload(); // Refresh page to update UI
    };
  }

  // Function to handle redirection for Sastra Charcha button
  function redirectToCharcha() {
    if (token) {
      // If the token exists, verify it
      fetch('https://thevera-botveradb.hf.space/validate_token', {
        method: 'GET',
        headers: {
          'Authorization': `Bearer ${token}`
        }
      })
      .then(response => response.json())
      .then(data => {
        if (data.message === "Token is valid!") {
          // Token is valid, redirect to Sastra Charcha page
          window.location.href = 'https://thevera-shastracharcha.static.hf.space';
          window.location.href = 'sastra.html';
        } else {
          // Token is invalid, redirect to registration page
          localStorage.removeItem('authToken'); // Clear invalid token
          window.location.href = 'login.html';
        }
      })
      .catch(error => {
        console.error('Error:', error);
        localStorage.removeItem('authToken'); // Clear token on error
        window.location.href = 'login.html'; // Redirect to registration if there's an error
      });
    } else {
      // No token, redirect to registration page
      window.location.href = 'login.html';
    }
  }

  // Attach the redirect function to the button
  if (charchaButton) {
    charchaButton.addEventListener('click', redirectToCharcha);
  }
});


if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
        navigator.serviceWorker.register('/service-worker.js')
            .then(registration => {
                console.log('ServiceWorker registered: ', registration);
            })
            .catch(error => {
                console.log('ServiceWorker registration failed: ', error);
            });
    });
}


// Check if the browser supports the Web Speech API
if (!('webkitSpeechRecognition' in window)) {
  alert("Your browser doesn't support speech recognition. Please use Google Chrome.");
} else {
  // Initialize speech recognition
  const recognition = new webkitSpeechRecognition();
  recognition.continuous = false;
  recognition.interimResults = false;
  recognition.lang = 'en-IN'; // Default language (can be 'hi-IN' for Hindi)

  const micButton = document.getElementById('micButton'); // Microphone icon
  const userInput = document.getElementById('userInput'); // Text input field
  const chatBody = document.getElementById('chatBody'); // Chat history container

  // Voice Input Button Click Event
  micButton.addEventListener('click', () => {
      if (micButton.classList.contains('active')) {
          recognition.stop(); // Stop if already active
      } else {
          recognition.start(); // Start listening
      }
  });

  // When speech recognition starts
  recognition.onstart = () => {
      micButton.classList.add('active'); // Change mic color to green
  };

  // When speech recognition ends
  recognition.onend = () => {
      micButton.classList.remove('active'); // Reset mic color to red
  };

  // When speech recognition result is detected
  recognition.onresult = (event) => {
      const transcript = event.results[0][0].transcript;
      userInput.value = transcript; // Fill the input with transcribed text
      sendMessage(); // Call sendMessage after getting the input
  };

  // Handle errors during speech recognition
  recognition.onerror = (event) => {
      alert('Speech recognition error: ' + event.error);
      micButton.classList.remove('active'); // Reset mic color to red if error occurs
  };
}

// Add an event listener to the input field to detect the Enter key
const userInput = document.getElementById('userInput');

userInput.addEventListener('keydown', function(event) {
    // Check if the Enter key (key code 13) is pressed
    if (event.key === 'Enter') {
        event.preventDefault(); // Prevent the default behavior (new line)
        sendMessage(); // Call your send message function
    }
});


let isSpeakEnabled = true;

function toggleHistory() {
  const historyPanel = document.querySelector('.history-panel');
  const chatHistoryText = document.querySelector('.chat-history-text');
  
  // Toggle the width of the history panel
  if (historyPanel.style.width === '0px') {
      historyPanel.style.width = '250px'; // Open the panel
      chatHistoryText.style.display = 'block'; // Show "Chat History" text
  } else {
      historyPanel.style.width = '0px'; // Close the panel
      chatHistoryText.style.display = 'none'; // Hide "Chat History" text
  }
}


function toggleMenu() {
  const menu = document.getElementById("menuOptions");
  menu.style.display = menu.style.display === "block" ? "none" : "block";
}

function openSettings() {
  document.getElementById("settingsModal").style.display = "block";
  document.getElementById("menuOptions").style.display = "none"; // Close menu when settings open
}

function closeSettings() {
  document.getElementById("settingsModal").style.display = "none";
}

function toggleSpeak() {
  const speakToggle = document.getElementById("speakToggle");
  isSpeakEnabled = speakToggle.checked;
  console.log(isSpeakEnabled ? "Speech enabled" : "Speech disabled");
}


// Close the modal when clicking outside of it
window.onclick = function(event) {
  const modal = document.getElementById("settingsModal");
  if (event.target === modal) {
    closeSettings();
  }
}


function startNewChat() {
  // Select the chat body element
  const chatBody = document.getElementById('chatBody');

  // Remove all chat messages
  chatBody.innerHTML = ''; // This clears all existing messages

  // Optionally, add the default welcome message again
  const welcomeMessage = document.createElement('div');
  welcomeMessage.classList.add('bot-message');
  welcomeMessage.textContent = "Hello! How can I assist you today?";

  chatBody.appendChild(welcomeMessage);

  // Scroll to the top after resetting chat
  chatBody.scrollTop = chatBody.scrollHeight;
}

function remove_special_chars(text) {
  // Allow only specified characters
  const allow = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 :,.?!";
  // Replace <br> with a space for better readability
  text = text.replace(/<br>/g, " ");
  let newtxt = "";
  // Iterate through the text and include only allowed characters
  for (let char of text) {
    if (allow.includes(char)) {
      newtxt += char;
    }
  }
  return newtxt;
}



// Helper function to speak text and execute a callback when done
function speakTextSequential(text, language, callback) {
    if (!isSpeakEnabled) {
        console.log('Speech is disabled.');
        if (callback) callback(); // Call callback even if speech is disabled
        return;  // Exit if speech is disabled
    }

    // Clean the text of HTML tags
    text = text.replace(/<\/?[^>]+(>|$)/g, "");

    if ('speechSynthesis' in window) {
        // Cancel any ongoing speech synthesis to avoid overlap
        window.speechSynthesis.cancel();

        const utterance = new SpeechSynthesisUtterance(text);

        // Set the language based on the input
        switch (language) {
            case 'hi':
                utterance.lang = 'hi-IN';  // Hindi
                break;
            case 'en':
            default:
                utterance.lang = 'en-IN';  // English (India)
                break;
        }

        // Set voice preferences to find a male voice
        const voices = window.speechSynthesis.getVoices();
        const maleVoice = voices.find(voice => {
            return (voice.name.includes('Google') || voice.name.includes('Indian')) && voice.name.toLowerCase().includes('male');
        });

        if (maleVoice) {
            utterance.voice = maleVoice;
        } else {
            // If no specific male voice found, fallback to any voice
            const defaultVoice = voices.find(voice => voice.name.includes('Google') || voice.name.includes('Indian'));
            if (defaultVoice) {
                utterance.voice = defaultVoice;
            }
        }

        // Set pitch, rate, and volume for a more natural sound
        utterance.pitch = 1;  // Adjust pitch for a male voice
        utterance.rate = 1;   // Normal speed
        utterance.volume = 1; // Maximum volume

        // Insert pauses for a more teaching-like effect
        const pauseDuration = 500; // Pause duration in milliseconds
        const splitText = text.split(/(?<=[.!?])\s+/); // Split text by punctuation and following spaces
        const speakingOrder = splitText.map(part => part.trim()).filter(part => part); // Clean up split results and filter out empty strings

        // Function to speak the segments sequentially
        const speakSegment = (index) => {
            if (index < speakingOrder.length) {
                const segment = speakingOrder[index];
                if (segment) {
                    utterance.text = segment; // Set the text to speak
                    speechSynthesis.speak(utterance);
                    utterance.onend = () => speakSegment(index + 1); // Speak next segment after the current one ends
                } else {
                    speakSegment(index + 1); // Move to the next index if the segment is empty
                }
            } else {
                if (callback) {
                    callback(); // Call the callback when done
                }
            }
        };

        // Start speaking the first segment
        speakSegment(0);

        // Handle potential speech synthesis errors
        utterance.onerror = function(event) {
            console.error('SpeechSynthesisUtterance error:', event.error);
            if (callback) {
                callback(); // Call callback even if there's an error
            }
        };

    } else {
        alert('Text-to-Speech not supported in your browser.');
        if (callback) {
            callback(); // Call callback if TTS is not supported
        }
    }
}



// Format bot response and handle categories
function formatBotResponse(rawResponse) {
  // Replace newlines with actual <br> for line breaks
  let rawResponseList = rawResponse.split('\n');
  let category = rawResponseList.length > 0 ? rawResponseList[0] : "General"; // Use ternary for category assignment
  let onlyResponse = rawResponseList.slice(1).join('\n'); // Use slice to skip the first element

  let formattedResponse = onlyResponse
      .replace(/\n/g, '<br>') // Replace newline with line breaks
      .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>') // Bold text between ** **
      .replace(/\*(.*?)\*/g, '<em>$1</em>') // Italic text between * *
      .replace(/(\d+\.\s.*?)(?=\n|$)/g, '<li>$1</li>'); // Convert numbered lists

  // Wrap list items in <ul> tags
  formattedResponse = formattedResponse.replace(/(<li>.*?<\/li>)+/g, '<ul>$&</ul>');

  return { formattedResponse, category }; // Return an object for clarity
}


function sendMessage() {
  const message = userInput.value.trim();

  if (message !== "") {
    appendMessage(message, 'user-message');
    userInput.value = '';

    // Disable the mic button to prevent multiple submissions during processing
    micButton.disabled = true;

    let username = null;
    let isRegisteredUser = false;

    // Try to get the user info from the token stored in local storage
    try {
      const token = localStorage.getItem('authToken');
      if (token) {
        const userObject = jwt_decode(token); // Decode the JWT token to get user info
        username = userObject.email; // Extract username (email) from the decoded token
        isRegisteredUser = !!username; // Check if user is registered (truthy if email exists)
      }
    } catch (error) {
      console.error("Error decoding token or no token found:", error);
    }

    // Prepare the request data to send to the backend
    const requestData = {
      user_data: message,
      bot_data: null // Placeholder for the bot's response
    };

    // Send the user message to the backend for processing
    fetch('https://thevera-backendvera.hf.space/generate_result', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ message: message })
    })
    .then(response => {
      if (!response.ok) {
        throw new Error("Failed to generate result");
      }
      return response.json();
    })
    .then(data => {
      let botResponses = data.response;
      const language = data.language || 'en';
    
      const { formattedResponse: botResponse, category } = formatBotResponse(botResponses); // Destructure correctly
      
      appendMessage(category, 'bot-message'); // Show the category
    
      // Regular expression to match all mantras or sloks within [[ ]]
      const mantraRegex = /\[\[(.*?)\]\]/g; 
      let lastIndex = 0; // Keep track of the last index processed
      let blocks = []; // Array to hold the sections of text and mantras
    
      let match;
    
      // Loop over all mantra matches and build blocks array
      while ((match = mantraRegex.exec(botResponse)) !== null) {
        const mantraText = match[1].trim(); // Extract the mantra/slok content
        const mantraStartIndex = match.index; // Start of mantra/slok
    
        // Extract the text before this mantra and add it to blocks
        const beforeMantraText = botResponse.substring(lastIndex, mantraStartIndex).trim();
        if (beforeMantraText) {
          blocks.push({ type: 'text', content: beforeMantraText });
        }
    
        // Add the mantra/slok to the blocks
        blocks.push({ type: 'mantra', content: mantraText });
    
        // Update the last index to move past the current mantra/slok
        lastIndex = mantraRegex.lastIndex;
      }
    
      // Add any remaining text after the last mantra/slok
      const afterLastMantraText = botResponse.substring(lastIndex).trim();
      if (afterLastMantraText) {
        blocks.push({ type: 'text', content: afterLastMantraText });
      }
    
      // Process the blocks sequentially
      processSequentially(blocks, language);
      
  
      // Store the conversation in MongoDB
      requestData.bot_data = botResponse; // Add the bot's response before saving
  
      // Determine backend URL for storing the chat
      const baseURL = 'https://thevera-botveradb.hf.space';
      const storeChatURL = isRegisteredUser 
        ? `${baseURL}/store_registered_chat/${username}` 
        : `${baseURL}/store_anonymous_chat`;
  
      // Store chat data
      return fetch(storeChatURL, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(requestData)
      });
    })
    .then(response => {
      if (!response.ok) {
          throw new Error("Failed to store chat data");
      }
      return response.json();
    })
    .then(data => {
      console.log(data.message); // Success message for storing chat
      micButton.disabled = false; // Re-enable mic button after response
    })
    .catch(error => {
      alert('Failed to connect to the backend. Please try again later.');
      console.error('Error:', error);
      micButton.disabled = false; // Re-enable mic button after error
    });
  }
}

// Manta Block Function
// Recursive function to process each block sequentially
function processSequentially(blocks, language, index = 0) {
  if (index >= blocks.length) {
    return; // Exit if all blocks are processed
  }

  const block = blocks[index];

  if (block.type === 'text') {
    // Show and speak the text block
    appendMessage(block.content, 'bot-message');
    speakTextSequential(block.content, language, () => {
      // Move to the next block once speaking is done
      processSequentially(blocks, language, index + 1);
    });
  } else if (block.type === 'mantra') {
    // Show and speak the mantra block
    displayMantra(block.content);
    speakMantraSequential(block.content, 1, () => {
      // Move to the next block once the mantra is spoken
      processSequentially(blocks, language, index + 1);
    });
  }
}

// Function to display the mantra block
function displayMantra(mantraText) {
    const mantraBlock = document.createElement('div');
    mantraBlock.className = 'mantra-block'; // Add class for styling
    mantraBlock.innerHTML = `<pre id="mantraText">${mantraText}</pre>
        <label for="repeat-count">Repeat mantra:</label>
        <div id="repeat-control">
            <button onclick="decreaseCount()">-</button>
            <input type="number" id="repeat-count" value="1" min="1" max="100" />
            <button onclick="increaseCount()">+</button>
        </div>
        <div class="play-mantra-button-container">
            <button class="play-mantra-button" onclick="repeatMantra()">&#9654;</button> <!-- Play button icon -->
        </div>`;
  
    document.getElementById('chatBody').appendChild(mantraBlock); // Append to chat body
}


// Function to hide the mantra block when there are no mantras
function hideMantraBlock() {
  let mantraBlock = document.getElementById('mantra-block');
  mantraBlock.style.display = 'none';
}

// Function to decrease the repeat count
function decreaseCount() {
    let repeatCountInput = document.getElementById('repeat-count');
    let currentValue = parseInt(repeatCountInput.value);
    
    if (currentValue > 1) {
        repeatCountInput.value = currentValue - 1;
    }
}

// Function to increase the repeat count
function increaseCount() {
    let repeatCountInput = document.getElementById('repeat-count');
    let currentValue = parseInt(repeatCountInput.value);
    
    repeatCountInput.value = currentValue + 1;
}


// Function to speak the mantra with repeat functionality
function speakMantraSequential(mantraText, repeatCount, callback) {
    const utterance = new SpeechSynthesisUtterance(mantraText);
    utterance.lang = 'sa-IN'; // Sanskrit
    utterance.rate = 0.8; // Slow speech for mantras
    utterance.pitch = 1.0; // Natural pitch
    
    utterance.onend = function() {
        if (repeatCount > 1) {
            repeatCount--;
            speechSynthesis.speak(utterance); // Speak again if more repetitions are needed
        } else if (callback) {
            callback(); // Call the callback when done
        }
    };

    // Handle potential speech synthesis errors
    utterance.onerror = function(event) {
        console.error('SpeechSynthesisUtterance error:', event.error);
        if (callback) {
            callback(); // Call callback even if there's an error
        }
    };

    // Cancel any ongoing speech synthesis before speaking
    window.speechSynthesis.cancel();
    speechSynthesis.speak(utterance);
}



// Function to handle mantra repetition based on user input
function repeatMantra() {
    let mantraText = document.getElementById('mantraText').textContent;
    let repeatCount = parseInt(document.getElementById('repeat-count').value);

    if (repeatCount < 1) {
        alert("Repeat count must be at least 1");
        return;
    }

    // Speak the mantra the number of times entered by the user
    speakMantraSequential(mantraText, repeatCount, 1);
}

// Mantra Black Function extends

let isFirstMessage = true; // Flag to track if it's the first message

// Function to speak the mantra
function appendMessage(text, className) {
    // Remove the default message when the user sends the first message
    if (isFirstMessage) {
        const welcomeMessage = document.querySelector('.welcome-message');
        if (welcomeMessage) {
            welcomeMessage.remove();
        }
        isFirstMessage = false;
    }
    const messageElement = document.createElement('div');
    messageElement.classList.add('user-message', className);
  
    // Use innerHTML to allow formatted content (e.g., bold, italic, line breaks)
    messageElement.innerHTML = text;
    chatBody.appendChild(messageElement);
    chatBody.scrollTop = chatBody.scrollHeight; // Auto scroll to the latest message
}

// Donate Logic
// Toggle menu visibility
// function toggleMenu() {
//   const menuOptions = document.getElementById('menuOptions');
//   menuOptions.style.display = menuOptions.style.display === 'none' ? 'block' : 'none';
// }

// Show donate modal
function showDonateModal() {
  document.getElementById('donateModal').style.display = 'block';
}

// Close donate modal
function closeDonateModal() {
  document.getElementById('donateModal').style.display = 'none';
}

// Copy UPI ID to clipboard
function copyUpiId() {
  const upiId = document.getElementById("upiId").innerText;
  navigator.clipboard.writeText(upiId).then(() => {
    alert("UPI ID copied to clipboard");
  }).catch(err => {
    console.error('Could not copy text: ', err);
  });
}