package allen.town.podcast.model.playback;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import allen.town.podcast.model.feed.Chapter;
import allen.town.podcast.model.feed.Feed;
import allen.town.podcast.model.feed.FeedItem;
import allen.town.podcast.model.feed.FeedMedia;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * Playable implementation for media for which a local version of
 * {@link FeedMedia} hasn't been found.
 * Used for Casting and for previewing unsubscribed feeds.
 */
public class RemoteMedia implements Playable {
    public static final String TAG = "RemoteMedia";

    public static final int PLAYABLE_TYPE_REMOTE_MEDIA = 3;

    private final String downloadUrl;
    private final String itemIdentifier;
    private final String feedUrl;
    private final String feedTitle;
    private final String episodeTitle;
    private final String episodeLink;
    private final String feedAuthor;
    private final String imageUrl;
    private final String feedLink;
    private final String mimeType;
    private final Date pubDate;
    private final String notes;
    private List<Chapter> chapters;
    private int duration;
    private int position;
    private long lastPlayedTime;

    public RemoteMedia(String downloadUrl, String itemId, String feedUrl, String feedTitle,
                       String episodeTitle, String episodeLink, String feedAuthor,
                       String imageUrl, String feedLink, String mimeType, Date pubDate,
                       String notes) {
        this.downloadUrl = downloadUrl;
        this.itemIdentifier = itemId;
        this.feedUrl = feedUrl;
        this.feedTitle = feedTitle;
        this.episodeTitle = episodeTitle;
        this.episodeLink = episodeLink;
        this.feedAuthor = feedAuthor;
        this.imageUrl = imageUrl;
        this.feedLink = feedLink;
        this.mimeType = mimeType;
        this.pubDate = pubDate;
        this.notes = notes;
    }

    public RemoteMedia(FeedItem item) {
        this.downloadUrl = item.getMedia().getDownload_url();
        this.itemIdentifier = item.getItemIdentifier();
        this.feedUrl = item.getFeed().getDownload_url();
        this.feedTitle = item.getFeed().getTitle();
        this.episodeTitle = item.getTitle();
        this.episodeLink = item.getLink();
        this.feedAuthor = item.getFeed().getAuthor();
        if (!TextUtils.isEmpty(item.getImageUrl())) {
            this.imageUrl = item.getImageUrl();
        } else {
            this.imageUrl = item.getFeed().getImageUrl();
        }
        this.feedLink = item.getFeed().getLink();
        this.mimeType = item.getMedia().getMime_type();
        this.pubDate = item.getPubDate();
        this.notes = item.getDescription();
    }

    public String getEpisodeIdentifier() {
        return itemIdentifier;
    }

    public String getFeedUrl() {
        return feedUrl;
    }

    public String getDownloadUrl() {
        return downloadUrl;
    }

    public String getEpisodeLink() {
        return episodeLink;
    }

    public String getFeedAuthor() {
        return feedAuthor;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public String getFeedLink() {
        return feedLink;
    }

    public String getMimeType() {
        return mimeType;
    }

    public Date getPubDate() {
        return pubDate;
    }

    public String getNotes() {
        return notes;
    }

    @Override
    public void writeToPreferences(SharedPreferences.Editor prefEditor) {
        //it seems pointless to do it, since the session should be kept by the remote device.
    }

    @Override
    public String getEpisodeTitle() {
        return episodeTitle;
    }

    @Override
    public List<Chapter> getChapters() {
        return chapters;
    }

    @Override
    public String getWebsiteLink() {
        if (episodeLink != null) {
            return episodeLink;
        } else {
            return feedUrl;
        }
    }

    @Override
    public String getFeedTitle() {
        return feedTitle;
    }

    @Override
    public Object getIdentifier() {
        return itemIdentifier + "@" + feedUrl;
    }

    @Override
    public int getDuration() {
        return duration;
    }

    @Override
    public int getPosition() {
        return position;
    }

    @Override
    public long getLastPlayedTime() {
        return lastPlayedTime;
    }

    @Override
    public MediaType getMediaType() {
        return MediaType.fromMimeType(mimeType);
    }

    @Override
    public String getLocalMediaUrl() {
        return null;
    }

    @Override
    public String getStreamUrl() {
        return downloadUrl;
    }

    @Override
    public boolean localFileAvailable() {
        return false;
    }

    @Override
    public void setPosition(int newPosition) {
        position = newPosition;
    }

    @Override
    public void setDuration(int newDuration) {
        duration = newDuration;
    }

    @Override
    public void setLastPlayedTime(long lastPlayedTimestamp) {
        lastPlayedTime = lastPlayedTimestamp;
    }

    @Override
    public void onPlaybackStart() {
        // no-op
    }

    @Override
    public void onPlaybackPause(Context context) {
        // no-op
    }

    @Override
    public void onPlaybackCompleted(Context context) {
        // no-op
    }

    @Override
    public int getPlayableType() {
        return PLAYABLE_TYPE_REMOTE_MEDIA;
    }

    @Override
    public void setChapters(List<Chapter> chapters) {
        this.chapters = chapters;
    }

    @Override
    @Nullable
    public String getImageLocation() {
        return imageUrl;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public String getDescription() {
        return notes;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(downloadUrl);
        dest.writeString(itemIdentifier);
        dest.writeString(feedUrl);
        dest.writeString(feedTitle);
        dest.writeString(episodeTitle);
        dest.writeString(episodeLink);
        dest.writeString(feedAuthor);
        dest.writeString(imageUrl);
        dest.writeString(feedLink);
        dest.writeString(mimeType);
        dest.writeLong((pubDate != null) ? pubDate.getTime() : 0);
        dest.writeString(notes);
        dest.writeInt(duration);
        dest.writeInt(position);
        dest.writeLong(lastPlayedTime);
    }

    public static final Parcelable.Creator<RemoteMedia> CREATOR = new Parcelable.Creator<RemoteMedia>() {
        @Override
        public RemoteMedia createFromParcel(Parcel in) {
            RemoteMedia result = new RemoteMedia(in.readString(), in.readString(), in.readString(),
                    in.readString(), in.readString(), in.readString(), in.readString(), in.readString(),
                    in.readString(), in.readString(), new Date(in.readLong()), in.readString());
            result.setDuration(in.readInt());
            result.setPosition(in.readInt());
            result.setLastPlayedTime(in.readLong());
            return result;
        }

        @Override
        public RemoteMedia[] newArray(int size) {
            return new RemoteMedia[size];
        }
    };

    @Override
    public boolean equals(Object other) {
        if (other instanceof RemoteMedia) {
            RemoteMedia rm = (RemoteMedia) other;
            return TextUtils.equals(downloadUrl, rm.downloadUrl)
                    && TextUtils.equals(feedUrl, rm.feedUrl)
                    && TextUtils.equals(itemIdentifier, rm.itemIdentifier);
        }
        if (other instanceof FeedMedia) {
            FeedMedia fm = (FeedMedia) other;
            if (!TextUtils.equals(downloadUrl, fm.getStreamUrl())) {
                return false;
            }
            FeedItem fi = fm.getItem();
            if (fi == null || !TextUtils.equals(itemIdentifier, fi.getItemIdentifier())) {
                return false;
            }
            Feed feed = fi.getFeed();
            return feed != null && TextUtils.equals(feedUrl, feed.getDownload_url());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder()
                .append(downloadUrl)
                .append(feedUrl)
                .append(itemIdentifier)
                .toHashCode();
    }
}
