package ru.yandex.webmaster3.core.semantic.review_business.auto.model.agg.impl.wrapper;

import com.google.common.base.Preconditions;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.AutoModeration;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.HProduct;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.agg.AggAutoReview;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.impl.wrapper.BaseAutoReviewWrapper;
import ru.yandex.webmaster3.core.semantic.review_business.model.Author;

import java.util.*;

import static ru.yandex.webmaster3.core.semantic.review_business.Collections.join;

/**
 * User: Evgeny Zhoga (ezhoga@yandex-team.ru)
 * Date: 24/9/12
 * Time: 6:57 PM
 */
public class AggAutoReviewWrapper extends AggAutoReview {
    private final AggAutoReview review;
    private final BaseAutoReviewWrapper baseReview;

    public static AggAutoReviewWrapper newReview() {
        return EMPTY_AGG_AUTO_REVIEW_WRAPPER;
    }

    public AggAutoReviewWrapper(final AggAutoReview review) {

        this(review, new BaseAutoReviewWrapper(review));
    }

    private AggAutoReviewWrapper(AggAutoReview review, BaseAutoReviewWrapper baseReview) {
        Preconditions.checkNotNull(review, "Unable to wrap null AggAutoReview!");

        this.review = review;
        this.baseReview = baseReview;
    }

    @Override
    public String getLanguage() {
        return baseReview.getLanguage();
    }

    public AggAutoReviewWrapper setLanguage(final String language) {
        return wrapBaseReview(baseReview.setLanguage(language));
    }

    @Override
    public Collection<String> getReviewsUrl() {
        return review.getReviewsUrl();
    }

    public AggAutoReviewWrapper setReviewsUrl(final Collection<String> reviewsUrl) {
        return new AggAutoReviewWrapper(this) {
            @Override
            public Collection<String> getReviewsUrl() {
                return Collections.unmodifiableCollection(reviewsUrl);
            }
        };
    }

    public AggAutoReviewWrapper setReviewsUrl(final String... reviewsUrl) {
        return setReviewsUrl(Arrays.asList(reviewsUrl));
    }

    @SuppressWarnings("unchecked")
    public AggAutoReviewWrapper addReviewsUrl(final Collection<String> reviewsUrl) {
        return new AggAutoReviewWrapper(this) {
            @Override
            public Collection<String> getReviewsUrl() {
                return join(super.getReviewsUrl(), reviewsUrl);
            }
        };
    }

    public AggAutoReviewWrapper addReviewsUrl(final String... reviewsUrl) {
        return addReviewsUrl(Arrays.asList(reviewsUrl));
    }


    @Override
    public String getSummary() {
        return baseReview.getSummary();
    }

    public AggAutoReviewWrapper setSummary(final String summary) {
        return wrapBaseReview(baseReview.setSummary(summary));
    }

    @Override
    public Date getWatchTime() {
        return baseReview.getWatchTime();
    }

    public AggAutoReviewWrapper setWatchTime(final Date watchTime) {
        return wrapBaseReview(baseReview.setWatchTime(watchTime));
    }

    @Override
    public HProduct getItem() {
        return baseReview.getItem();
    }

    @Override
    public Collection<String> getPhotos() {
        return baseReview.getPhotos();
    }

    public AggAutoReviewWrapper addPhotos(final String... photos) {
        return wrapBaseReview(baseReview.addPhotos(photos));
    }

    public AggAutoReviewWrapper addPhotos(final Collection<String> photos) {
        return wrapBaseReview(baseReview.addPhotos(photos));
    }

    public AggAutoReviewWrapper setPhotos(final String... photos) {
        return wrapBaseReview(baseReview.setPhotos(photos));
    }

    public AggAutoReviewWrapper setPhotos(final Collection<String> photos) {
        return wrapBaseReview(baseReview.setPhotos(photos));
    }

    public AggAutoReviewWrapper setItem(final HProduct item) {
        return wrapBaseReview(baseReview.setItem(item));
    }

    @Override
    public Long getSourceId() {
        return review.getSourceId();
    }

    public AggAutoReviewWrapper setSourceId(final Long sourceId) {
        return new AggAutoReviewWrapper(this) {
            @Override
            public Long getSourceId() {
                return sourceId;
            }
        };
    }

    @Override
    public String getDomain() {
        return review.getDomain();
    }

    public AggAutoReviewWrapper setDomain(final String domain) {
        return new AggAutoReviewWrapper(this) {
            @Override
            public String getDomain() {
                return domain;
            }
        };
    }

    @Override
    public Collection<String> getPros() {
        return baseReview.getPros();
    }

    public AggAutoReviewWrapper addPros(final String... pros) {
        return wrapBaseReview(baseReview.addPros(pros));
    }

    @SuppressWarnings("unchecked")
    public AggAutoReviewWrapper addPros(final Collection<String> pros) {
        return wrapBaseReview(baseReview.addPros(pros));
    }

    public AggAutoReviewWrapper setPros(final String... pros) {
        return wrapBaseReview(baseReview.setPros(pros));
    }

    public AggAutoReviewWrapper setPros(final Collection<String> pros) {
        return wrapBaseReview(baseReview.setPros(pros));
    }

    @Override
    public Collection<String> getContras() {
        return baseReview.getContras();
    }

    public AggAutoReviewWrapper addContras(final String... contras) {
        return wrapBaseReview(baseReview.addContras(contras));
    }

    @SuppressWarnings("unchecked")
    public AggAutoReviewWrapper addContras(final Collection<String> contras) {
        return wrapBaseReview(baseReview.addContras(contras));
    }

    public AggAutoReviewWrapper setContras(final String... contras) {
        return wrapBaseReview(baseReview.setContras(contras));
    }

    public AggAutoReviewWrapper setContras(final Collection<String> contras) {
        return wrapBaseReview(baseReview.setContras(contras));
    }

    @Override
    public String getId() {
        return baseReview.getId();
    }

    public AggAutoReviewWrapper setId(final String id) {
        return wrapBaseReview(baseReview.setId(id));
    }

    @Override
    public Float getRating() {
        return baseReview.getRating();
    }

    public AggAutoReviewWrapper setRating(final Float rating) {
        return wrapBaseReview(baseReview.setRating(rating));
    }


    @Override
    public Float getBestRating() {
        return baseReview.getBestRating();
    }

    public AggAutoReviewWrapper setBestRating(final float bestRating) {
        return wrapBaseReview(baseReview.setBestRating(bestRating));
    }

    @Override
    public Float getWorstRating() {
        return baseReview.getWorstRating();
    }

    public AggAutoReviewWrapper setWorstRating(final float worstRating) {
        return wrapBaseReview(baseReview.setWorstRating(worstRating));
    }

    @Override
    public Author getReviewer() {
        return baseReview.getReviewer();
    }

    public AggAutoReviewWrapper setReviewer(final Author reviewer) {
        return wrapBaseReview(baseReview.setReviewer(reviewer));
    }


    @Override
    public Date getReviewedDate() {
        return baseReview.getReviewedDate();
    }

    public AggAutoReviewWrapper setReviewedDate(final Date reviewedDate) {
        return wrapBaseReview(baseReview.setReviewedDate(reviewedDate));
    }


    @Override
    public String getUrl() {
        return review.getUrl();
    }

    public AggAutoReviewWrapper setUrl(final String url) {
        return new AggAutoReviewWrapper(this) {
            @Override
            public String getUrl() {
                return url;
            }
        };
    }

    @Override
    public String getPermanentId() {
        return baseReview.getPermanentId();
    }

    public AggAutoReviewWrapper setPermanentId(final String permanentId) {
        return wrapBaseReview(baseReview.setPermanentId(permanentId));
    }

    @Override
    public String getVersionId() {
        return baseReview.getVersionId();
    }

    public AggAutoReviewWrapper setVersionId(final String versionId) {
        return wrapBaseReview(baseReview.setVersionId(versionId));
    }


    @Override
    public String getDescription() {
        return baseReview.getDescription();
    }

    public AggAutoReviewWrapper setDescription(final String description) {
        return wrapBaseReview(baseReview.setDescription(description));
    }

    @Override
    public List<AutoModeration> getModerationHistory() {
        return baseReview.getModerationHistory();
    }

    public AggAutoReviewWrapper setModerationHistory(final List<AutoModeration> history) {
        return wrapBaseReview(baseReview.setModerationHistory(history));
    }

    public AggAutoReviewWrapper setModerationHistory(final AutoModeration... history) {
        return wrapBaseReview(baseReview.setModerationHistory(history));
    }

    public AggAutoReviewWrapper addModerationHistory(final List<AutoModeration> history) {
        return wrapBaseReview(baseReview.addModerationHistory(history));
    }

    public AggAutoReviewWrapper addModerationHistory(final AutoModeration... history) {
        return wrapBaseReview(baseReview.addModerationHistory(history));
    }

    @Override
    public boolean isDeleted() {
        return baseReview.isDeleted();
    }

    public AggAutoReviewWrapper setDeleted(final boolean isDeleted) {
        return wrapBaseReview(baseReview.setDeleted(isDeleted));
    }

    @Override
    public Integer getUsefulCount() {
        return baseReview.getUsefulCount();
    }

    public AggAutoReviewWrapper setUsefulCount(final Integer usefulCount) {
        return wrapBaseReview(baseReview.setUsefulCount(usefulCount));
    }

    @Override
    public Integer getUselessCount() {
        return review.getUselessCount();
    }

    public AggAutoReviewWrapper setUselessCount(final Integer uselessCount) {
        return wrapBaseReview(baseReview.setUselessCount(uselessCount));
    }

    @Override
    public List<String> getPhotoUrls() {
        return baseReview.getPhotoUrls();
    }

    public AggAutoReviewWrapper setPhotoUrls(final List<String> photoUrls) {
        return wrapBaseReview(baseReview.setPhotoUrls(photoUrls));
    }

    public AggAutoReviewWrapper setPhotoUrls(final String... photoUrls) {
        return setPhotoUrls(Arrays.asList(photoUrls));
    }

    @SuppressWarnings("unchecked")
    public AggAutoReviewWrapper addPhotoUrls(final List<String> photoUrls) {
        return wrapBaseReview(baseReview.addPhotoUrls(photoUrls));
    }


    private AggAutoReviewWrapper wrapBaseReview(final BaseAutoReviewWrapper baseReview) {
        return new AggAutoReviewWrapper(this, baseReview);
    }

    private final static AggAutoReviewWrapper EMPTY_AGG_AUTO_REVIEW_WRAPPER =
            new AggAutoReviewWrapper(new AggAutoReview() {
                @Override
                public Collection<String> getReviewsUrl() {
                    return Collections.emptyList();
                }

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

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

                @Override
                public Date getWatchTime() {
                    return null;
                }

                @Override
                public HProduct getItem() {
                    return null;
                }

                @Override
                public Collection<String> getPhotos() {
                    return Collections.emptyList();
                }

                @Override
                public Long getSourceId() {
                    return null;
                }

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

                @Override
                public Collection<String> getPros() {
                    return Collections.emptyList();
                }

                @Override
                public Collection<String> getContras() {
                    return Collections.emptyList();
                }

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

                @Override
                public Float getRating() {
                    return null;
                }

                @Override
                public Float getBestRating() {
                    return null;
                }

                @Override
                public Float getWorstRating() {
                    return null;
                }

                @Override
                public Author getReviewer() {
                    return null;
                }

                @Override
                public Date getReviewedDate() {
                    return null;
                }

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

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

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

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

                @Override
                public List<AutoModeration> getModerationHistory() {
                    return Collections.emptyList();
                }

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

                @Override
                public Integer getUsefulCount() {
                    return null;
                }

                @Override
                public Integer getUselessCount() {
                    return null;
                }

                @Override
                public List<String> getPhotoUrls() {
                    return Collections.emptyList();
                }
            });
}
