package ru.yandex.webmaster3.core.semantic.review_business.biz.model;

import org.json.JSONException;
import ru.yandex.webmaster3.core.semantic.review_business.ModelUtils;
import ru.yandex.webmaster3.core.semantic.review_business.biz.model.impl.json.UgcBizReviewJsonConversions;
import ru.yandex.webmaster3.core.semantic.review_business.model.UserIdentity;
import ru.yandex.webmaster3.core.semantic.review_business.ModelUtils;
import ru.yandex.webmaster3.core.semantic.review_business.biz.model.impl.json.UgcBizReviewJsonConversions;
import ru.yandex.webmaster3.core.semantic.review_business.model.UserIdentity;

import java.util.Locale;

/**
 * Represents BizReview created on the service.
 * It's BizReview with detailed info about author.
 * <p/>
 * Getters of this class are used to count hashCode, so to keep contract (see first point in {@link Object#hashCode()})
 * they should return objects which have same hashCode value during application run time
 * In general - implementation should be immutable and return references which are also immutable
 * <p/>
 * User: willzyx
 * Date: 3/30/12 - 6:53 PM
 */
public abstract class UgcBizReview extends BizReview {

    /**
     * Source from review created
     */
    public enum SourceType {
        DESKTOP_MAPS,
        MOBILE_MAPS
    }

    /**
     * UID is primary key in the passport database.
     * For details see
     * http://doc.yandex-team.ru/Passport/AuthDevGuide/concepts/Account_About.xml
     *
     * @return review author's UID
     */
    public abstract Long getUid();

    /**
     * Unique device ID when review has been written from mobile device.
     */
    public abstract String getUuid();

    /**
     * User domain (from which domain review has been written).
     */
    public abstract String getDomain();

    /**
     * User interface language (which language was selected at preferences at the moment of review creation)
     */
    public abstract Locale getUiLanguage();

    /**
     * Information about user environment at the time of review creation:
     * * User-Agent
     * * Cookies
     * * IP
     * * etc...
     */
    public abstract UserIdentity getUserIdentity();

    /**
     * Comment can be left by business which was reviewed by this review
     *
     * @return comment left by business
     */
    @Deprecated
    public abstract String getCommentFromBusiness();

    /**
     * @return comment from biz on this review or null if there is no comment
     */
    public abstract Comment getComment();

    /**
     * Because of user generated content is versioning
     * we should preserve relationship between versions
     *
     * @return VersionID of previous version of review
     *         or null when we meet initial version of review
     */
    public abstract String getPreviousVersionId();

    public abstract SourceType getSourceType();

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof UgcBizReview)) return false;
        if (!super.equals(o)) return false;

        final UgcBizReview that = (UgcBizReview) o;

        return hashCode() == that.hashCode()
                && ModelUtils.equals(getUid(), that.getUid())
                && ModelUtils.equals(getUserIdentity(), that.getUserIdentity())
                && ModelUtils.equals(getCommentFromBusiness(), that.getCommentFromBusiness())
                && ModelUtils.equals(getSourceType(), that.getSourceType())
                && ModelUtils.equals(getComment(), that.getComment());
    }

    @Override
    public int hashCode() {
        return ModelUtils.hashCode("ugc-biz-review",
                super.hashCode()
                , getUid()
                , getUserIdentity()
                , getCommentFromBusiness()
                , getSourceType()
                , getComment()
        );
    }

    /**
     * Construct string representation of BizReview.
     * All not-null and not-empty members will be presented there.
     */
    @Override
    public String toString() {
        try {
            return UgcBizReviewJsonConversions.toJson(this).toString(1);
        } catch (JSONException e) {
            throw new AssertionError("Not expected to be thrown");
        }
    }
}

