module Invidious::Routes::API::V1::Misc
  # Stats API endpoint for Invidious
  def self.stats(env)
    env.response.content_type = "application/json"

    if !CONFIG.statistics_enabled
      return {"software" => SOFTWARE}.to_json
    else
      return Invidious::Jobs::StatisticsRefreshJob::STATISTICS.to_json
    end
  end

  # APIv1 currently uses the same logic for both
  # user playlists and Invidious playlists. This means that we can't
  # reasonably split them yet. This should be addressed in APIv2
  def self.get_playlist(env : HTTP::Server::Context)
    env.response.content_type = "application/json"
    plid = env.params.url["plid"]

    offset = env.params.query["index"]?.try &.to_i?
    offset ||= env.params.query["page"]?.try &.to_i?.try { |page| (page - 1) * 100 }
    offset ||= 0

    video_id = env.params.query["continuation"]?

    format = env.params.query["format"]?
    format ||= "json"

    if plid.starts_with? "RD"
      return env.redirect "/api/v1/mixes/#{plid}"
    end

    begin
      playlist = get_playlist(plid)
    rescue ex : InfoException
      return error_json(404, ex)
    rescue ex
      return error_json(404, "Playlist does not exist.")
    end

    user = env.get?("user").try &.as(User)
    if !playlist || playlist.privacy.private? && playlist.author != user.try &.email
      return error_json(404, "Playlist does not exist.")
    end

    # includes into the playlist a maximum of 20 videos, before the offset
    if offset > 0
      lookback = offset < 50 ? offset : 50
      response = playlist.to_json(offset - lookback)
      json_response = JSON.parse(response)
    else
      #  Unless the continuation is really the offset 0, it becomes expensive.
      #  It happens when the offset is not set.
      #  First we find the actual offset, and then we lookback
      #  it shouldn't happen often though

      lookback = 0
      response = playlist.to_json(offset, video_id: video_id)
      json_response = JSON.parse(response)

      if json_response["videos"].as_a[0]["index"] != offset
        offset = json_response["videos"].as_a[0]["index"].as_i
        lookback = offset < 50 ? offset : 50
        response = playlist.to_json(offset - lookback)
        json_response = JSON.parse(response)
      end
    end

    if format == "html"
      playlist_html = template_playlist(json_response)
      index, next_video = json_response["videos"].as_a.skip(1 + lookback).select { |video| !video["author"].as_s.empty? }[0]?.try { |v| {v["index"], v["videoId"]} } || {nil, nil}

      response = {
        "playlistHtml" => playlist_html,
        "index"        => index,
        "nextVideo"    => next_video,
      }.to_json
    end

    response
  end

  def self.mixes(env)
    locale = env.get("preferences").as(Preferences).locale

    env.response.content_type = "application/json"

    rdid = env.params.url["rdid"]

    continuation = env.params.query["continuation"]?
    continuation ||= rdid.lchop("RD")[0, 11]

    format = env.params.query["format"]?
    format ||= "json"

    begin
      mix = fetch_mix(rdid, continuation, locale: locale)

      if !rdid.ends_with? continuation
        mix = fetch_mix(rdid, mix.videos[1].id)
        index = mix.videos.index(mix.videos.select { |video| video.id == continuation }[0]?)
      end

      mix.videos = mix.videos[index..-1]
    rescue ex
      return error_json(500, ex)
    end

    response = JSON.build do |json|
      json.object do
        json.field "title", mix.title
        json.field "mixId", mix.id

        json.field "videos" do
          json.array do
            mix.videos.each do |video|
              json.object do
                json.field "title", video.title
                json.field "videoId", video.id
                json.field "author", video.author

                json.field "authorId", video.ucid
                json.field "authorUrl", "/channel/#{video.ucid}"

                json.field "videoThumbnails" do
                  json.array do
                    generate_thumbnails(json, video.id)
                  end
                end

                json.field "index", video.index
                json.field "lengthSeconds", video.length_seconds
              end
            end
          end
        end
      end
    end

    if format == "html"
      response = JSON.parse(response)
      playlist_html = template_mix(response)
      next_video = response["videos"].as_a.select { |video| !video["author"].as_s.empty? }[0]?.try &.["videoId"]

      response = {
        "playlistHtml" => playlist_html,
        "nextVideo"    => next_video,
      }.to_json
    end

    response
  end
end
