package io.delphiplatform.api.v3.model.trackposition;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDate;
import java.util.Objects;

import javax.validation.Valid;
import javax.validation.constraints.Pattern;

import io.delphiplatform.api.util.model.ModelUtils;
import io.delphiplatform.api.v3.constant.ApplicationConstants;
import io.delphiplatform.api.v3.constant.DspConstants;
import io.delphiplatform.api.v3.model.Playlist;
import io.delphiplatform.api.v3.model.PlaylistableModel;
import io.delphiplatform.api.v3.model.TrackAwareModel;
import io.delphiplatform.api.v3.model.TrackPosition;
import io.delphiplatform.api.v3.model.TrackSimple;
import io.delphiplatform.api.v3.model.amazon.AmazonTrackShortInfo;
import io.delphiplatform.api.v3.model.amazon.StreamingFor1DaysInfo;
import io.delphiplatform.api.v3.model.amazon.StreamingFor7DaysInfo;

/**
 * PlaylistTrackPosition
 */
@Deprecated
@JsonPropertyOrder(alphabetic = true)
public class PlaylistTrackPosition extends TrackPosition implements PlaylistableModel, TrackAwareModel {

    @JsonIgnore
    private String trackId;

    @JsonIgnore
    private String countryCode;

    @JsonProperty("playlist_id")
    private String playlistId;

    @JsonProperty("playlist")
    private Playlist playlist;

    @JsonProperty("streams")
    private Long streams;

    @JsonProperty("streaming_for_1_days")
    private StreamingFor1DaysInfo streamingFor1Days;

    @JsonProperty("streaming_for_7_days")
    private StreamingFor7DaysInfo streamingFor7Days;

    @JsonProperty("trend")
    private Long trend;

    @JsonProperty("num_days_on")
    private Long daysInPlaylist;

    @JsonProperty("earliest_position_date")
    @DateTimeFormat(
        iso = DateTimeFormat.ISO.DATE)
    private LocalDate earliestPositionDate;

    @JsonProperty("latest_position_date")
    @DateTimeFormat(
        iso = DateTimeFormat.ISO.DATE)
    private LocalDate latestPositionDate;

    @JsonProperty("earliest_position")
    private Long earliestPosition;

    @JsonProperty("previous_position_change_14_days")
    private Long previousPositionChange14Days;

    @JsonProperty("trend_change_14_days")
    private Long trendChange14Days;

    @JsonProperty("last_date_change_14_days")
    @DateTimeFormat(
        iso = DateTimeFormat.ISO.DATE)
    private LocalDate lastDateChange14Days;

    @JsonProperty("track")
    private TrackSimple track;

    @JsonProperty("amazon_track")
    private AmazonTrackShortInfo amazonTrack;

    public PlaylistTrackPosition trackId(String trackId) {
        this.trackId = trackId;
        return this;
    }

    /**
     * Get track id
     *
     * @return trackId
     */
    public String getTrackId() {
        return trackId;
    }

    public void setTrackId(String trackId) {
        this.trackId = trackId;
    }

    public PlaylistTrackPosition countryCode(String countryCode) {
        this.countryCode = countryCode;
        return this;
    }

    /**
     * Get country code
     *
     * @return countryCode
     */
    public String getCountryCode() {
        return countryCode;
    }

    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }

    public PlaylistTrackPosition isrc(String isrc) {
        this.isrc = isrc;
        return this;
    }

    /**
     * The International Standard Recording Code (ISRC) for a song.
     *
     * @return isrc
     */
    @Pattern(regexp = ApplicationConstants.ISRC_PATTERN)
    public String getIsrc() {
        return isrc;
    }

    public void setIsrc(String isrc) {
        this.isrc = isrc;
    }

    public PlaylistTrackPosition dsp(String dsp) {
        this.dsp = dsp;
        return this;
    }

    /**
     * Slug name of a DSP
     *
     * @return dsp
     */
    @Pattern(regexp = "^[a-z]*$")
    public String getDsp() {
        return dsp;
    }

    public void setDsp(String dsp) {
        this.dsp = dsp;
    }

    public PlaylistTrackPosition current(Long current) {
        this.current = current;
        return this;
    }

    /**
     * Get current
     *
     * @return current
     */
    public Long getCurrent() {
        return current;
    }

    public void setCurrent(Long current) {
        this.current = current;
    }

    public PlaylistTrackPosition previous(Long previous) {
        this.previous = previous;
        return this;
    }

    /**
     * Get previous
     *
     * @return previous
     */
    public Long getPrevious() {
        return previous;
    }

    public void setPrevious(Long previous) {
        this.previous = previous;
    }

    public PlaylistTrackPosition top(Integer top) {
        this.top = top;
        return this;
    }

    /**
     * Get top
     *
     * @return top
     */
    public Integer getTop() {
        return top;
    }

    public void setTop(Integer top) {
        this.top = top;
    }

    public PlaylistTrackPosition numWeeksOn(Integer numWeeksOn) {
        this.numWeeksOn = numWeeksOn;
        return this;
    }

    /**
     * Get numWeeksOn
     *
     * @return numWeeksOn
     */
    public Integer getNumWeeksOn() {
        return numWeeksOn;
    }

    public void setNumWeeksOn(Integer numWeeksOn) {
        this.numWeeksOn = numWeeksOn;
    }

    public PlaylistTrackPosition date(LocalDate date) {
        this.date = date;
        return this;
    }

    /**
     * ISO 8601 date in format `YYYY-MM-DD`
     *
     * @return date
     */
    @Valid
    @Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$")
    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public PlaylistTrackPosition playlistId(String playlistId) {
        this.playlistId = playlistId;
        return this;
    }

    /**
     * Primary key identifier for Playlist
     *
     * @return playlistId
     */
    public String getPlaylistId() {
        return playlistId;
    }

    public void setPlaylistId(String playlistId) {
        this.playlistId = playlistId;
    }

    public PlaylistTrackPosition playlist(Playlist playlist) {
        this.playlist = playlist;
        return this;
    }

    /**
     * Get playlist
     *
     * @return playlist
     */
    @Valid
    public Playlist getPlaylist() {
        return playlist;
    }

    public void setPlaylist(Playlist playlist) {
        this.playlist = playlist;
    }

    public PlaylistTrackPosition streams(Long streams) {
        this.streams = streams;
        return this;
    }

    /**
     * The number of streams, aggregated by provided filter parameters.
     *
     * @return streams
     */
    public Long getStreams() {
        return streams;
    }

    public void setStreams(Long streams) {
        this.streams = streams;
    }

    public PlaylistTrackPosition streamingFor7Days(StreamingFor7DaysInfo streamingFor7Days) {
        this.streamingFor7Days = streamingFor7Days;
        return this;
    }

    /**
     * Get streaming info for 7 days
     *
     * @return streamingFor7Days
     */
    public StreamingFor7DaysInfo getStreamingFor7Days() {
        return streamingFor7Days;
    }

    public void setStreamingFor7Days(StreamingFor7DaysInfo streamingFor7Days) {
        this.streamingFor7Days = streamingFor7Days;
    }

    public PlaylistTrackPosition streamingFor1Days(StreamingFor1DaysInfo streamingFor1Days) {
        this.streamingFor1Days = streamingFor1Days;
        return this;
    }

    public StreamingFor1DaysInfo getStreamingFor1Days() {
        return streamingFor1Days;
    }

    public void setStreamingFor1Days(StreamingFor1DaysInfo streamingFor1Days) {
        this.streamingFor1Days = streamingFor1Days;
    }

    public PlaylistTrackPosition trend(Long trend) {
        this.trend = trend;
        return this;
    }

    /**
     * Get trend
     *
     * @return trend
     */
    public Long getTrend() {
        return trend;
    }

    public void setTrend(Long trend) {
        this.trend = trend;
    }

    public PlaylistTrackPosition daysInPlaylist(Long daysInPlaylist) {
        this.daysInPlaylist = daysInPlaylist;
        return this;
    }

    /**
     * Get number of track days in playlist
     *
     * @return daysInPlaylist
     */
    public Long getDaysInPlaylist() {
        return daysInPlaylist;
    }

    public void setDaysInPlaylist(Long daysInPlaylist) {
        this.daysInPlaylist = daysInPlaylist;
    }

    public PlaylistTrackPosition earliestPositionDate(LocalDate earliestPositionDate) {
        this.earliestPositionDate = earliestPositionDate;
        return this;
    }

    /**
     * Get earliest position date
     *
     * @return earliestPositionDate
     */
    public LocalDate getEarliestPositionDate() {
        return earliestPositionDate;
    }

    public void setEarliestPositionDate(LocalDate earliestPositionDate) {
        this.earliestPositionDate = earliestPositionDate;
    }

    public PlaylistTrackPosition latestPositionDate(LocalDate latestPositionDate) {
        this.latestPositionDate = latestPositionDate;
        return this;
    }

    /**
     * Get latest position date
     *
     * @return latestPositionDate
     */
    public LocalDate getLatestPositionDate() {
        return latestPositionDate;
    }

    public void setLatestPositionDate(LocalDate latestPositionDate) {
        this.latestPositionDate = latestPositionDate;
    }

    public PlaylistTrackPosition previousPositionChange14Days(Long previousPositionChange14Days) {
        this.previousPositionChange14Days = previousPositionChange14Days;
        return this;
    }

    /**
     * Get previous position change in 14 days
     *
     * @return previousPositionChange14Days
     */
    public Long getPreviousPositionChange14Days() {
        return previousPositionChange14Days;
    }

    public void setPreviousPositionChange14Days(Long previousPositionChange14Days) {
        this.previousPositionChange14Days = previousPositionChange14Days;
    }

    public PlaylistTrackPosition trendChange14Days(Long trendChange14Days) {
        this.trendChange14Days = trendChange14Days;
        return this;
    }

    /**
     * Get trend change in 14 days
     *
     * @return trendChange14Days
     */
    public Long getTrendChange14Days() {
        return trendChange14Days;
    }

    public void setTrendChange14Days(Long trendChange14Days) {
        this.trendChange14Days = trendChange14Days;
    }

    public PlaylistTrackPosition lastDateChange14Days(LocalDate lastDateChange14Days) {
        this.lastDateChange14Days = lastDateChange14Days;
        return this;
    }

    /**
     * Get last date change in 14 days
     *
     * @return lastDateChange14Days
     */
    public LocalDate getLastDateChange14Days() {
        return lastDateChange14Days;
    }

    public void setLastDateChange14Days(LocalDate lastDateChange14Days) {
        this.lastDateChange14Days = lastDateChange14Days;
    }

    public PlaylistTrackPosition track(TrackSimple track) {
        this.track = track;
        return this;
    }

    /**
     * Get GRAS track metadata
     *
     * @return track
     */
    public TrackSimple getTrack() {
        return track;
    }

    public void setTrack(TrackSimple track) {
        this.track = track;
    }

    public PlaylistTrackPosition amazonTrack(AmazonTrackShortInfo amazonTrack) {
        this.amazonTrack = amazonTrack;
        return this;
    }

    /**
     * Get amazon track metadata
     *
     * @return amazonTrack
     */
    public AmazonTrackShortInfo getAmazonTrack() {
        return amazonTrack;
    }

    public void setAmazonTrack(AmazonTrackShortInfo amazonTrack) {
        this.amazonTrack = amazonTrack;
    }

    public Long getEarliestPosition() {
        return earliestPosition;
    }

    public void setEarliestPosition(Long earliestPosition) {
        this.earliestPosition = earliestPosition;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        PlaylistTrackPosition playlistTrackPosition = (PlaylistTrackPosition) o;
        return Objects.equals(this.trackId, playlistTrackPosition.trackId) &&
            Objects.equals(this.countryCode, playlistTrackPosition.countryCode) &&
            Objects.equals(this.isrc, playlistTrackPosition.isrc) &&
            Objects.equals(this.dsp, playlistTrackPosition.dsp) &&
            Objects.equals(this.current, playlistTrackPosition.current) &&
            Objects.equals(this.previous, playlistTrackPosition.previous) &&
            Objects.equals(this.top, playlistTrackPosition.top) &&
            Objects.equals(this.numWeeksOn, playlistTrackPosition.numWeeksOn) &&
            Objects.equals(this.date, playlistTrackPosition.date) &&
            Objects.equals(this.playlistId, playlistTrackPosition.playlistId) &&
            Objects.equals(this.playlist, playlistTrackPosition.playlist) &&
            Objects.equals(this.streams, playlistTrackPosition.streams) &&
            Objects.equals(this.trend, playlistTrackPosition.trend) &&
            Objects.equals(this.daysInPlaylist, playlistTrackPosition.daysInPlaylist) &&
            Objects.equals(this.earliestPositionDate, playlistTrackPosition.earliestPositionDate) &&
            Objects.equals(this.latestPositionDate, playlistTrackPosition.latestPositionDate) &&
            Objects.equals(this.streamingFor7Days, playlistTrackPosition.streamingFor7Days) &&
            Objects.equals(this.streamingFor1Days, playlistTrackPosition.streamingFor1Days) &&
            Objects.equals(this.previousPositionChange14Days, playlistTrackPosition.previousPositionChange14Days) &&
            Objects.equals(this.trendChange14Days, playlistTrackPosition.trendChange14Days) &&
            Objects.equals(this.lastDateChange14Days, playlistTrackPosition.lastDateChange14Days) &&
            Objects.equals(this.track, playlistTrackPosition.track) &&
            Objects.equals(this.amazonTrack, playlistTrackPosition.amazonTrack);
    }

    @Override
    public int hashCode() {
        return Objects.hash(trackId, countryCode, isrc, dsp, current, previous, top, numWeeksOn, date, playlistId, playlist, streams,
            trend, daysInPlaylist, earliestPositionDate, latestPositionDate, streamingFor7Days, streamingFor1Days,
            previousPositionChange14Days, trendChange14Days, lastDateChange14Days, track, amazonTrack);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("class PlaylistTrackPosition {\n");

        sb.append("    trackId: ").append(toIndentedString(trackId)).append("\n");
        sb.append("    countryCode: ").append(toIndentedString(countryCode)).append("\n");
        sb.append("    isrc: ").append(toIndentedString(isrc)).append("\n");
        sb.append("    dsp: ").append(toIndentedString(dsp)).append("\n");
        sb.append("    current: ").append(toIndentedString(current)).append("\n");
        sb.append("    previous: ").append(toIndentedString(previous)).append("\n");
        sb.append("    top: ").append(toIndentedString(top)).append("\n");
        sb.append("    numWeeksOn: ").append(toIndentedString(numWeeksOn)).append("\n");
        sb.append("    date: ").append(toIndentedString(date)).append("\n");
        sb.append("    playlistId: ").append(toIndentedString(playlistId)).append("\n");
        sb.append("    playlist: ").append(toIndentedString(playlist)).append("\n");
        sb.append("    streams: ").append(toIndentedString(streams)).append("\n");
        sb.append("    trend: ").append(toIndentedString(trend)).append("\n");
        sb.append("    daysInPlaylist: ").append(toIndentedString(daysInPlaylist)).append("\n");
        sb.append("    earliestPositionDate: ").append(toIndentedString(earliestPositionDate)).append("\n");
        sb.append("    latestPositionDate: ").append(toIndentedString(latestPositionDate)).append("\n");
        sb.append("    streamingFor7Days: ").append(toIndentedString(streamingFor7Days)).append("\n");
        sb.append("    streamingFor1Days: ").append(toIndentedString(streamingFor1Days)).append("\n");
        sb.append("    previousPositionChange14Days: ").append(toIndentedString(previousPositionChange14Days)).append("\n");
        sb.append("    trendChange14Days: ").append(toIndentedString(trendChange14Days)).append("\n");
        sb.append("    lastDateChange14Days: ").append(toIndentedString(lastDateChange14Days)).append("\n");
        sb.append("    track: ").append(toIndentedString(track)).append("\n");
        sb.append("    amazonTrack: ").append(toIndentedString(amazonTrack)).append("\n");
        sb.append("}");
        return sb.toString();
    }

    @JsonIgnore
    public String getAmazonTrackIdUnPrefixed() {
        if (!DspConstants.AMAZON.equals(getDsp())) {
            throw new IllegalStateException("Only Amazon DSP is supported");
        }

        return ModelUtils.getAmazonTrackIdUnPrefixed(getTrackId());
    }

    @JsonIgnore
    public String getBasePlaylistIdFromAmazonFullPlaylistId() {
        if (!DspConstants.AMAZON.equals(getDsp())) {
            throw new IllegalStateException("Only Amazon DSP is supported");
        }

        return ModelUtils.getBasePlaylistIdFromAmazonFullPlaylistId(getPlaylistId());
    }

    /**
     * Convert the given object to string with each line indented by 4 spaces (except the first line).
     */
    private String toIndentedString(Object o) {
        if (o == null) {
            return "null";
        }
        return o.toString().replace("\n", "\n    ");
    }
}
