import { Injectable, signal, inject, computed } from '@angular/core'; import { Storage } from '@ionic/storage-angular'; import { Canto, CantiService } from './canti.service'; import { ComunitaService } from './comunita.service'; import * as QRCode from 'qrcode'; @Injectable({ providedIn: 'root' }) export class PlaylistService { private storage = inject(Storage); private cantiService = inject(CantiService); private comunitaService = inject(ComunitaService); public selectionMode = signal(false); public selectedIds = signal>(new Set()); public playlists = signal([]); public lastPlaylist = signal(null); public autoPlayPlaylist = signal(false); public activeListIds = signal([]); public activeListName = signal(null); public activePlaylistId = signal(null); private _storage: Storage | null = null; // Community scalette exposed as playlists (only when community filter is active) public comunitaPlaylists = computed(() => { if (!this.comunitaService.comunitaCode() || !this.comunitaService.isFilterActive()) { return []; } return this.comunitaService.comunitaScalette().map(s => ({ id: s.id, name: s.name, ids: s.ids, createdAt: s.date, isComunita: true })); }); // Merged list: personal playlists + community scalette public allPlaylists = computed(() => { const community = this.comunitaPlaylists(); const personal = this.playlists(); if (community.length > 0) { return [...community, ...personal.map(p => ({ ...p, isComunita: false }))]; } return personal.map(p => ({ ...p, isComunita: false })); }); constructor() { this.init(); } async init() { const storage = await this.storage.create(); this._storage = storage; const saved = await this._storage.get('playlists'); if (saved) { this.playlists.set(saved); } const last = await this._storage?.get('lastPlaylist'); if (last) { this.lastPlaylist.set(last); } } toggleSelectionMode() { this.selectionMode.update(v => !v); if (!this.selectionMode()) { this.selectedIds.set(new Set()); } } toggleSongSelection(id: string) { if (!this.selectionMode()) { const active = this.activeListIds(); if (active.length > 0) { this.selectedIds.set(new Set(active)); } this.selectionMode.set(true); } this.selectedIds.update(set => { const newSet = new Set(set); if (newSet.has(id)) { newSet.delete(id); } else { newSet.add(id); } return newSet; }); } async savePlaylist(name: string, ids: string[]) { const editId = this.activePlaylistId(); let newPlaylist: any; if (editId) { this.playlists.update(p => p.map(pl => { if (pl.id === editId) { return { ...pl, name, ids }; } return pl; })); newPlaylist = this.playlists().find(pl => pl.id === editId); } else { newPlaylist = { id: Date.now().toString(), name, ids, createdAt: new Date() }; this.playlists.update(p => [newPlaylist, ...p]); } this.lastPlaylist.set(newPlaylist); this.activeListIds.set(ids); this.activeListName.set(name); await this._storage?.set('playlists', this.playlists()); await this._storage?.set('lastPlaylist', newPlaylist); // Reset selection mode, IDs and editing state after saving this.selectedIds.set(new Set()); this.selectionMode.set(false); this.activePlaylistId.set(newPlaylist.id); } async deletePlaylist(id: string) { this.playlists.update(p => p.filter(pl => pl.id !== id)); await this._storage?.set('playlists', this.playlists()); } async generateQR(ids: string[], name: string): Promise { const data = this.getShareLink(ids, name); return await QRCode.toDataURL(data, { width: 400, margin: 2, color: { dark: '#2d3436', light: '#ffffff' } }); } getShareLink(ids: string[], name: string): string { const data = JSON.stringify({ name, ids }); // Use btoa safely for UTF-8 strings const base64 = btoa(unescape(encodeURIComponent(data))); // Always use the production URL for sharing links as requested const productionUrl = 'https://www.canticristiani.it/ionic'; return `${productionUrl}/?import=${base64}`; } processImportJson(json: any): boolean { if (json && json.name && json.ids) { this.activeListIds.set(json.ids); this.activeListName.set(json.name); return true; } return false; } async sharePlaylistQR(ids: string[], name: string) { const qrImage = await this.generateQR(ids, name); const shareLink = this.getShareLink(ids, name); const fileName = `${name.toLowerCase().replace(/\s+/g, '_')}_qr.png`; try { const res = await fetch(qrImage); const blob = await res.blob(); const file = new File([blob], fileName, { type: 'image/png' }); if (navigator.share && navigator.canShare && navigator.canShare({ files: [file] })) { await navigator.share({ files: [file], title: 'Playlist CantiCristiani', text: `Ecco la playlist: ${name}\n\nClicca qui per aprirla subito: ${shareLink}` }); } else { // Fallback: download const link = document.createElement('a'); link.href = qrImage; link.download = fileName; link.click(); } } catch (err) { console.error('Share failed', err); } } async loadPlaylists() { } }