// src/util.ts
function decode(str) {
  return decodeURIComponent(str.replace(/\+/g, " "));
}
function encode(str) {
  return encodeURIComponent(str).replace(/%20/g, "+").replace(/[!'()*]/g, escape);
}

// src/spotify-uri.ts
var SpotifyUri = class {
  type;
  id;
  uri;
  constructor(uri, id, type) {
    this.uri = uri;
    this.id = id;
    this.type = type;
  }
  static is(v) {
    return typeof v === "object" && typeof v.uri === "string";
  }
  toURI() {
    return `spotify:${this.type}:${encode(this.id)}`;
  }
  toURL() {
    return `/${this.type}/${encode(this.id)}`;
  }
  toEmbedURL() {
    return `https://embed.spotify.com/?uri=${this.toURI()}`;
  }
  toOpenURL() {
    return `https://open.spotify.com${this.toURL()}`;
  }
  toPlayURL() {
    return `https://play.spotify.com${this.toURL()}`;
  }
};

// src/local.ts
var Local = class extends SpotifyUri {
  artist;
  album;
  track;
  seconds;
  constructor(uri, artist, album, track, seconds) {
    super(uri, "", "local" /* Local */);
    this.artist = artist;
    this.album = album;
    this.track = track;
    this.seconds = seconds;
  }
  static is(v) {
    return typeof v === "object" && v.type === "local";
  }
  toURI() {
    return `spotify:${this.type}:${encode(this.artist)}:${encode(
      this.album
    )}:${encode(this.track)}:${this.seconds}`;
  }
  toURL() {
    return `/${this.type}/${encode(this.artist)}/${encode(this.album)}/${encode(
      this.track
    )}/${this.seconds}`;
  }
};

// src/search.ts
var Search = class extends SpotifyUri {
  get query() {
    return this.id;
  }
  static is(v) {
    return typeof v === "object" && v.type === "search";
  }
};

// src/playlist.ts
var Playlist = class extends SpotifyUri {
  user;
  constructor(uri, id, user) {
    super(uri, id, "playlist" /* Playlist */);
    if (typeof user === "string") {
      this.user = user;
    }
  }
  static is(v) {
    return typeof v === "object" && v.type === "playlist";
  }
  toURI() {
    if (this.user !== void 0) {
      if (this.id === "starred") {
        return `spotify:user:${encode(this.user)}:${encode(this.id)}`;
      }
      return `spotify:user:${encode(this.user)}:playlist:${encode(this.id)}`;
    }
    return `spotify:playlist:${encode(this.id)}`;
  }
  toURL() {
    if (this.user !== void 0) {
      if (this.id === "starred") {
        return `/user/${encode(this.user)}/${encode(this.id)}`;
      }
      return `/user/${encode(this.user)}/playlist/${encode(this.id)}`;
    }
    return `/playlist/${encode(this.id)}`;
  }
};

// src/artist.ts
var Artist = class extends SpotifyUri {
  static is(v) {
    return typeof v === "object" && v.type === "artist";
  }
};

// src/album.ts
var Album = class extends SpotifyUri {
  static is(v) {
    return typeof v === "object" && v.type === "album";
  }
};

// src/track.ts
var Track = class extends SpotifyUri {
  static is(v) {
    return typeof v === "object" && v.type === "track";
  }
};

// src/episode.ts
var Episode = class extends SpotifyUri {
  static is(v) {
    return typeof v === "object" && v.type === "episode";
  }
};

// src/show.ts
var Show = class extends SpotifyUri {
  static is(v) {
    return typeof v === "object" && v.type === "show";
  }
};

// src/user.ts
var User = class extends SpotifyUri {
  get user() {
    return this.id;
  }
  static is(v) {
    return typeof v === "object" && v.type === "user";
  }
};

// src/parse.ts
function parse(input) {
  const uri = SpotifyUri.is(input) ? input.uri : input;
  const { protocol, hostname, pathname = "/", searchParams } = new URL(uri);
  if (hostname === "embed.spotify.com") {
    const parsedQs = Object.fromEntries(searchParams);
    if (typeof parsedQs.uri !== "string") {
      throw new Error(
        "Parsed query string was not valid: " + searchParams.toString()
      );
    }
    return parse(parsedQs.uri);
  }
  if (protocol === "spotify:") {
    const parts2 = uri.split(":");
    return parseParts(uri, parts2);
  }
  if (pathname === null) {
    throw new TypeError("No pathname");
  }
  const parts = pathname.split("/");
  return parseParts(uri, parts);
}
function parseParts(uri, parts) {
  parts = parts.filter((p) => !p.startsWith("intl"));
  let spotifyType = parts[1];
  if (spotifyType === "embed" /* Embed */) {
    parts = parts.slice(1);
    spotifyType = parts[1];
  }
  const len = parts.length;
  if (spotifyType === "search" /* Search */) {
    return new Search(uri, decode(parts.slice(2).join(":")), spotifyType);
  }
  if (len >= 3 && spotifyType === "local" /* Local */) {
    return new Local(
      uri,
      decode(parts[2]),
      decode(parts[3]),
      decode(parts[4]),
      +parts[5]
    );
  }
  if (len >= 4 || spotifyType === "playlist" /* Playlist */) {
    if (len >= 5) {
      return new Playlist(uri, decode(parts[4]), decode(parts[2]));
    }
    if (parts[3] === "starred") {
      return new Playlist(uri, "starred", decode(parts[2]));
    }
    return new Playlist(uri, decode(parts[2]));
  }
  if (len === 3 && spotifyType === "user" /* User */) {
    return new User(uri, decode(parts[2]), spotifyType);
  }
  if (spotifyType === "artist" /* Artist */) {
    return new Artist(uri, parts[2], spotifyType);
  }
  if (spotifyType === "album" /* Album */) {
    return new Album(uri, parts[2], spotifyType);
  }
  if (spotifyType === "track" /* Track */) {
    return new Track(uri, parts[2], spotifyType);
  }
  if (spotifyType === "episode" /* Episode */) {
    return new Episode(uri, parts[2], spotifyType);
  }
  if (spotifyType === "show" /* Show */) {
    return new Show(uri, parts[2], spotifyType);
  }
  throw new TypeError(`Could not determine type for: ${uri}`);
}

// src/index.ts
function formatURI(input) {
  const uri = typeof input === "string" ? parse(input) : input;
  return uri.toURI();
}
function formatEmbedURL(input) {
  const uri = typeof input === "string" ? parse(input) : input;
  return uri.toEmbedURL();
}
function formatOpenURL(input) {
  const uri = typeof input === "string" ? parse(input) : input;
  return uri.toOpenURL();
}
function formatPlayURL(input) {
  const uri = typeof input === "string" ? parse(input) : input;
  return uri.toPlayURL();
}
export {
  Album,
  Artist,
  Episode,
  Local,
  Playlist,
  Search,
  Show,
  Track,
  User,
  formatEmbedURL,
  formatOpenURL,
  formatPlayURL,
  formatURI,
  parse
};
