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

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

import org.openapitools.jackson.nullable.JsonNullable;
import org.springframework.format.annotation.DateTimeFormat;

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

import javax.validation.constraints.Min;

import io.delphiplatform.api.v3.model.service.ImageService;
import io.delphiplatform.api.v3.rdb.entity.video.ChartmetricVideoEntity;
import io.delphiplatform.api.v3.rdb.entity.video.VideoEntity;

/**
 * Object containing the metadata of a YouTube video.
 */
@JsonPropertyOrder(alphabetic = true)
public class Video {

    @JsonProperty("video_id")
    private String videoId;

    @JsonProperty("video_title")
    private String videoTitle;

    @JsonProperty("channel_id")
    private String channelId;

    @JsonProperty("dsp_channel_id")
    private String dspChannelId;

    @JsonProperty("channel_title")
    private String channelTitle;

    @JsonProperty("content_type")
    private YoutubeContentType contentType;

    @JsonProperty("date_uploaded")
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private JsonNullable<LocalDate> dateUploaded = JsonNullable.undefined();

    @JsonProperty("dsp")
    private VideoDspSlug dsp;

    @JsonProperty("dsp_video_id")
    private String dspVideoId;

    @JsonProperty("duration_seconds")
    private Long durationSeconds;

    @JsonProperty("views")
    private Long views;

    @JsonProperty("thumbnails")
    private YouTubeThumbnails thumbnails;

    public static Video from(VideoEntity entity, ImageService imageService) {
        return new Video()
            .videoId(entity.getVideoId())
            .videoTitle(entity.getTitle())
            .channelId(entity.getChannel() == null ? null : entity.getChannel().getChannelId())
            .dspChannelId(entity.getChannel() == null ? null : entity.getChannel().getDspChannelId())
            .channelTitle(entity.getChannel() == null ? null : entity.getChannel().getTitle())
            .contentType(entity.getContentType())
            .dateUploaded(entity.getDateUploaded())
            .dsp(entity.getDsp())
            .dspVideoId(entity.getDspVideoId())
            .durationSeconds(entity.getDurationSeconds())
            .views(entity.getViews())
            .thumbnails(imageService.resolveImage(entity));
    }

    public static Video from(ChartmetricVideoEntity entity, ImageService imageService) {
        if (entity.getSonyVideo() != null && entity.getIsSony()) {
            return from(entity.getSonyVideo(), imageService);
        }
        // for not sony videos are not populated: channel related info, contentType, durationSeconds
        return new Video()
            .videoId(entity.getVideoId())
            .videoTitle(entity.getTitle())
            .dateUploaded(entity.getDateUploaded())
            .dsp(entity.getDsp())
            .dspVideoId(entity.getDspVideoId())
            .views(entity.getViews())
            .thumbnails(imageService.resolveImage(entity));
    }

    public Video videoId(String videoId) {
        this.videoId = videoId;
        return this;
    }

    /**
     * Primary key identifier for a Video
     *
     * @return videoId
     */
    public String getVideoId() {
        return videoId;
    }

    public void setVideoId(String videoId) {
        this.videoId = videoId;
    }

    public Video videoTitle(String videoTitle) {
        this.videoTitle = videoTitle;
        return this;
    }

    /**
     * The video's title. The property value has a maximum length of 100 characters and may contain all valid UTF-8
     * characters except `<` and `>`.
     *
     * @return videoTitle
     */
    public String getVideoTitle() {
        return videoTitle;
    }

    public void setVideoTitle(String videoTitle) {
        this.videoTitle = videoTitle;
    }

    public Video channelId(String channelId) {
        this.channelId = channelId;
        return this;
    }

    /**
     * The ID for a YouTube channel. In the YouTube Data API, this is the value of a `channel` resource's id property.
     *
     * @return channelId
     */
    public String getChannelId() {
        return channelId;
    }

    public void setChannelId(String channelId) {
        this.channelId = channelId;
    }


    public Video dspChannelId(String dspChannelId) {
        this.dspChannelId = dspChannelId;
        return this;
    }

    public String getDspChannelId() {
        return dspChannelId;
    }

    public void setDspChannelId(String dspChannelId) {
        this.dspChannelId = dspChannelId;
    }

    public Video channelTitle(String channelTitle) {
        this.channelTitle = channelTitle;
        return this;
    }

    /**
     * Channel title for the channel that the video belongs to.
     *
     * @return channelTitle
     */
    public String getChannelTitle() {
        return channelTitle;
    }

    public void setChannelTitle(String channelTitle) {
        this.channelTitle = channelTitle;
    }

    public Video contentType(YoutubeContentType contentType) {
        this.contentType = contentType;
        return this;
    }

    /**
     * Get contentType
     *
     * @return contentType
     */
    public YoutubeContentType getContentType() {
        return contentType;
    }

    public void setContentType(YoutubeContentType contentType) {
        this.contentType = contentType;
    }

    public Video dateUploaded(LocalDate dateUploaded) {
        this.dateUploaded = JsonNullable.of(dateUploaded);
        return this;
    }

    /**
     * [ISO 8601 date](https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates) in format `YYYY-MM-DD`
     *
     * @return dateUploaded
     */
    public JsonNullable<LocalDate> getDateUploaded() {
        return dateUploaded;
    }

    public void setDateUploaded(JsonNullable<LocalDate> dateUploaded) {
        this.dateUploaded = dateUploaded;
    }

    public Video dsp(VideoDspSlug dsp) {
        this.dsp = dsp;
        return this;
    }

    /**
     * Get dsp
     *
     * @return dsp
     */
    public VideoDspSlug getDsp() {
        return dsp;
    }

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

    public Video dspVideoId(String dspVideoId) {
        this.dspVideoId = dspVideoId;
        return this;
    }

    /**
     * The ID of a YouTube video. In the YouTube Data API, this is the value of a `video` resource's id property.
     *
     * @return dspVideoId
     */
    public String getDspVideoId() {
        return dspVideoId;
    }

    public void setDspVideoId(String dspVideoId) {
        this.dspVideoId = dspVideoId;
    }

    public Video durationSeconds(Long durationSeconds) {
        this.durationSeconds = durationSeconds;
        return this;
    }

    /**
     * Duration in seconds. Unsigned integer. minimum: 0
     *
     * @return durationSeconds
     */
    @Min(0)
    public Long getDurationSeconds() {
        return durationSeconds;
    }

    public void setDurationSeconds(Long durationSeconds) {
        this.durationSeconds = durationSeconds;
    }

    public Video thumbnails(YouTubeThumbnails thumbnails) {
        this.thumbnails = thumbnails;
        return this;
    }

    public Video views(Long views) {
        this.views = views;
        return this;
    }

    public Long getViews() {
        return views;
    }

    public void setViews(Long views) {
        this.views = views;
    }

    /**
     * Get thumbnails
     *
     * @return thumbnails
     */
    public YouTubeThumbnails getThumbnails() {
        return thumbnails;
    }

    public void setThumbnails(YouTubeThumbnails thumbnails) {
        this.thumbnails = thumbnails;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Video video = (Video) o;
        return Objects.equals(this.videoId, video.videoId) &&
            Objects.equals(this.videoTitle, video.videoTitle) &&
            Objects.equals(this.channelId, video.channelId) &&
            Objects.equals(this.channelTitle, video.channelTitle) &&
            Objects.equals(this.contentType, video.contentType) &&
            Objects.equals(this.dateUploaded, video.dateUploaded) &&
            Objects.equals(this.dsp, video.dsp) &&
            Objects.equals(this.dspVideoId, video.dspVideoId) &&
            Objects.equals(this.durationSeconds, video.durationSeconds) &&
            Objects.equals(this.thumbnails, video.thumbnails);
    }

    @Override
    public int hashCode() {
        return Objects.hash(videoId, videoTitle, channelId, channelTitle, contentType, dateUploaded, dsp, dspVideoId,
            durationSeconds, thumbnails);
    }

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

        sb.append("    videoId: ").append(toIndentedString(videoId)).append("\n");
        sb.append("    videoTitle: ").append(toIndentedString(videoTitle)).append("\n");
        sb.append("    channelId: ").append(toIndentedString(channelId)).append("\n");
        sb.append("    channelTitle: ").append(toIndentedString(channelTitle)).append("\n");
        sb.append("    contentType: ").append(toIndentedString(contentType)).append("\n");
        sb.append("    dateUploaded: ").append(toIndentedString(dateUploaded)).append("\n");
        sb.append("    dsp: ").append(toIndentedString(dsp)).append("\n");
        sb.append("    dspVideoId: ").append(toIndentedString(dspVideoId)).append("\n");
        sb.append("    durationSeconds: ").append(toIndentedString(durationSeconds)).append("\n");
        sb.append("    thumbnails: ").append(toIndentedString(thumbnails)).append("\n");
        sb.append("}");
        return sb.toString();
    }

    /**
     * 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    ");
    }
}

