1package commands
2
3import (
4	"fmt"
5	"strconv"
6
7	"github.com/ambientsound/visp/log"
8	spotify_tracklist "github.com/ambientsound/visp/spotify/tracklist"
9	"github.com/google/uuid"
10	"github.com/zmb3/spotify"
11
12	"github.com/ambientsound/visp/api"
13)
14
15// Write saves a local tracklist to Spotify.
16type Write struct {
17	command
18	api    api.API
19	name   string
20	new    bool
21	public bool
22}
23
24// NewWrite returns Write.
25func NewWrite(api api.API) Command {
26	return &Write{
27		api: api,
28	}
29}
30
31// Parse implements Command.
32func (cmd *Write) Parse() error {
33	lit := cmd.ScanRemainderAsIdentifier()
34
35	cmd.setTabComplete(lit, []string{strconv.Quote(cmd.api.List().Name())})
36
37	if len(lit) > 0 {
38		cmd.name = lit
39	}
40
41	// TODO: private/public?
42
43	return nil
44}
45
46// Exec implements Command.
47func (cmd *Write) Exec() error {
48	client, err := cmd.api.Spotify()
49	if err != nil {
50		return err
51	}
52
53	tracklist := cmd.api.Tracklist()
54	if tracklist == nil {
55		return fmt.Errorf("only track lists can be saved to Spotify")
56	}
57
58	// Copy tracklist, assign new name, and save that one
59	if len(cmd.name) > 0 {
60		tracklist = tracklist.Copy()
61		tracklist.SetID(uuid.New().String())
62		tracklist.SetName(cmd.name)
63		cmd.api.Db().Cache(tracklist)
64	}
65
66	row := cmd.api.Db().RowByID(tracklist.ID())
67	if row == nil {
68		return fmt.Errorf("internal error: tracklist not cached in database")
69	}
70
71	user, err := client.CurrentUser()
72	if err != nil {
73		return err
74	}
75
76	ids := make([]spotify.ID, 0, tracklist.Len())
77	for _, track := range tracklist.Tracks() {
78		ids = append(ids, track.ID)
79	}
80
81	if !tracklist.HasRemote() {
82		remotelist, err := client.CreatePlaylistForUser(user.ID, tracklist.Name(), "", cmd.public)
83		if err != nil {
84			return fmt.Errorf("create remote playlist: %w", err)
85		}
86
87		tracklist.SetID(remotelist.ID.String())
88		tracklist.SetName(remotelist.Name)
89		tracklist.SetRemote(true)
90		row.SetID(tracklist.ID())
91
92		// Re-index original list in database if working on the old copy
93
94		cmd.api.SetList(tracklist)
95
96		snapshot, err := spotify_tracklist.AddTracksToPlaylist(client, remotelist.ID, ids)
97		if err != nil {
98			return fmt.Errorf("add tracks to remote playlist: %w", err)
99		}
100		_ = snapshot // todo: add and use this?
101
102		log.Infof("Created playlist '%s' with %d tracks", remotelist.Name, len(ids))
103
104	} else {
105
106		id := spotify.ID(tracklist.ID())
107		err := client.ChangePlaylistName(id, tracklist.Name())
108		if err != nil {
109			return fmt.Errorf("change remote playlist name: %w", err)
110		}
111
112		err = spotify_tracklist.ReplacePlaylistTracks(client, id, ids)
113		if err != nil {
114			return fmt.Errorf("write new track list to to remote playlist: %w", err)
115		}
116
117		log.Infof("Wrote changes to remote playlist '%s' with %d tracks", tracklist.Name(), len(ids))
118	}
119
120	tracklist.SetSyncedToRemote()
121
122	return nil
123}
124