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

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.json.JSONObject;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.*;
import ru.yandex.webmaster3.core.semantic.review_business.auto.model.impl.BaseAutoReviewAttributes;
import ru.yandex.webmaster3.core.semantic.review_business.model.Author;
import ru.yandex.webmaster3.core.semantic.review_business.model.impl.json.AuthorJsonConversions;
import ru.yandex.webmaster3.core.semantic.review_business.util.DateHelper;
import ru.yandex.webmaster3.core.semantic.review_business.util.JsonAccessUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import static com.google.common.base.Strings.emptyToNull;
import static ru.yandex.webmaster3.core.semantic.review_business.auto.model.impl.BaseAutoReviewAttributes.*;

/**
 * User: Evgeny Zhoga (ezhoga@yandex-team.ru)
 * Date: 5/10/12
 * Time: 1:08 PM
 */
@Slf4j
public class BaseAutoReviewOverJson extends BaseAutoReview {
    private final JSONObject json;

    public BaseAutoReviewOverJson(String json) throws JSONException {
        Preconditions.checkNotNull(emptyToNull(json), "Unable to create BaseAutoReview over empty JSON string");
        this.json = new JSONObject(json);
    }

    /**
     * This constructor is done to be hidden in children which require to build hierarchy of objects based on JSONObject
     */
    protected BaseAutoReviewOverJson(JSONObject json) {
        Preconditions.checkNotNull(json, "Unable to create BaseAutoReview over null JSON");

        this.json = json;
    }

    @Override
    public String getLanguage() {
        return json.optString(LANGUAGE, null);
    }

    @Override
    public String getId() {
        return json.optString(ID, null);
    }

    @Override
    public String getPermanentId() {
        return json.optString(PERMANENT_ID, null);
    }

    @Override
    public String getVersionId() {
        return json.optString(VERSION_ID, null);
    }

    @Override
    public Float getRating() {
        return JsonAccessUtils.optFloat(json, RATING);
    }

    @Override
    public Float getBestRating() {
        return JsonAccessUtils.optFloat(json, BEST_RATING);
    }

    @Override
    public Float getWorstRating() {
        return JsonAccessUtils.optFloat(json, WORST_RATING);
    }

    @Override
    public Author getReviewer() {
        final JSONObject authorAsJson = json.optJSONObject(REVIEWER);
        return authorAsJson == null ?
                null :
                AuthorJsonConversions.fromJson(authorAsJson);
    }

    @Override
    public Date getReviewedDate() {
        return DateHelper.read(json.optString(REVIEWED_DATE));
    }

    @Override
    public String getDescription() {
        return json.optString(DESCRIPTION, null);
    }

    @Override
    public String getSummary() {
        return json.optString(BaseAutoReviewAttributes.SUMMARY, null);
    }

    @Override
    public Date getWatchTime() {
        return DateHelper.read(json.optString(BaseAutoReviewAttributes.WATCH_TIME));
    }

    @Override
    public HProduct getItem() {
        final JSONObject itemAsJson = json.optJSONObject(BaseAutoReviewAttributes.ITEM);
        return itemAsJson == null ?
                null :
                HProductJsonConversions.fromJson(itemAsJson);
    }

    @Override
    public Collection<String> getPhotos() {
        try {
            return JsonAccessUtils.arrayToStrings(json.optJSONArray(BaseAutoReviewAttributes.PHOTO));
        } catch (JSONException e) {
            log.error("Error while getting pros", e);
            return Collections.emptyList();
        }
    }

    @Override
    public Collection<String> getPros() {
        try {
            return JsonAccessUtils.arrayToStrings(json.optJSONArray(BaseAutoReviewAttributes.PRO));
        } catch (JSONException e) {
            log.error("Error while getting pros", e);
            return Collections.emptyList();
        }
    }

    @Override
    public Collection<String> getContras() {
        try {
            return JsonAccessUtils.arrayToStrings(json.optJSONArray(BaseAutoReviewAttributes.CONTRA));
        } catch (JSONException e) {
            log.error("Error while getting contras", e);
            return Collections.emptyList();
        }
    }

    @Override
    public List<AutoModeration> getModerationHistory() {
        try {
            return Lists.transform(JsonAccessUtils.arrayToJsons(json.optJSONArray(BaseAutoReviewAttributes.MODERATION_HISTORY)),
                    AutoModerationJsonConversions.JSON_TO_MODERATION);
        } catch (JSONException e) {
            log.error("Error while getting moderation history from JSON", e);
            return Collections.emptyList();
        }
    }

    @Override
    public boolean isDeleted() {
        return json.optBoolean(DELETED, false);
    }

    @Override
    public Integer getUsefulCount() {
        return JsonAccessUtils.optInt(json, USEFUL);
    }

    @Override
    public Integer getUselessCount() {
        return JsonAccessUtils.optInt(json, USELESS);
    }

    @Override
    public List<String> getPhotoUrls() {
        try {
            return JsonAccessUtils.arrayToStrings(json.optJSONArray(BaseAutoReviewAttributes.PHOTO_URLS));
        } catch (JSONException e) {
            log.error("Error while getting pros", e);
            return Collections.emptyList();
        }
    }
}

