package ru.yandex.wmconsole.data.wrappers.api;

import ru.yandex.wmconsole.data.HostInfoStatusEnum;
import ru.yandex.wmconsole.data.VerificationStateEnum;
import ru.yandex.wmconsole.data.api.ApiCrawlingState;
import ru.yandex.wmconsole.data.api.ApiVerificationState;
import ru.yandex.wmconsole.data.info.api.ApiHostInfo;
import ru.yandex.wmtools.common.util.XmlDataWrapper;

/**
 * @author ailyin
 */
public class ApiHostInfoWrapper<T extends ApiHostInfo> extends XmlDataWrapper<T> {
    protected static final String TAG_NAME = "name";
    protected static final String TAG_VERIFICATION = "verification";
    protected static final String TAG_VERIFICATION_DETAILS = "details";
    protected static final String ATTRIBUTE_VERIFICATION_STATE = "state";
    private static final String TAG_CRAWLING_DETAILS = "details";
    private static final String ATTRIBUTE_CRAWLING_STATE = "state";

    private static final String TAG_CRAWLING = "crawling";
    protected static final String TAG_VIRUSED = "virused";

    private static final String TAG_TCY = "tcy";
    private static final String TAG_URLS = "url-count";
    private static final String TAG_INDEX_COUNT = "index-count";
    private static final String TAG_LAST_ACCESS = "last-access";

    public ApiHostInfoWrapper(T info) {
        super(info, "host", "id", Long.toString(info.getId()));
    }

    @Override
    protected void doToXml(StringBuilder result) {
        putHostnameTag(result, TAG_NAME, data.getName());

        ApiVerificationState verState = ApiVerificationState.getByVerifcationStateAndType(
                data.getVerificationState(), data.getVerificationType());
        VerificationStateEnum verDetails = (ApiVerificationState.VERIFICATION_FAILED.equals(verState) &&
                !data.getVerificationState().isInternal()) ? data.getVerificationState() : null;
        XmlDataWrapper<VerificationStateEnum> verificationDetailsWrapper =
                verDetails != null ? new InnerElementWrapper(verDetails, TAG_VERIFICATION_DETAILS) : null;
        putComplexTag(result, TAG_VERIFICATION, verificationDetailsWrapper,
                ATTRIBUTE_VERIFICATION_STATE, verState.toString());
        if (!ApiVerificationState.VERIFIED.equals(verState)) {
            return;
        }

        long urlCount = data.getUrls() == null ? 0 : data.getUrls();
        long indexCount = data.getIndexCount() == null ? 0 : data.getIndexCount();

        if (urlCount < indexCount) {
            urlCount = indexCount;
        }

        boolean indexed = urlCount > 0;
        ApiCrawlingState crawlingState = ApiCrawlingState.INDEXED;
        if (!indexed) {
            crawlingState = (HostInfoStatusEnum.WAITING.equals(data.getHostInfoStatus()) ||
                    HostInfoStatusEnum.FINISHED.equals(data.getHostInfoStatus()))?
                    ApiCrawlingState.WAITING : ApiCrawlingState.NOT_INDEXED;
        }
        HostInfoStatusEnum crawlingDetails = (!indexed && (data.getHostInfoStatus() != null) &&
                !data.getHostInfoStatus().isInternal()) ? data.getHostInfoStatus() : null;
        XmlDataWrapper<HostInfoStatusEnum> crawlingDetailWrapper =
                crawlingDetails != null ? new InnerElementWrapper(crawlingDetails, TAG_CRAWLING_DETAILS) : null;
        putComplexTag(result, TAG_CRAWLING, crawlingDetailWrapper,
                ATTRIBUTE_CRAWLING_STATE, crawlingState.toString());
        putBooleanTag(result, TAG_VIRUSED, data.isVirused());
        if (!indexed) {
            return;
        }

        putDateTimeTag(result, TAG_LAST_ACCESS, data.getLastAccess());
        putIntegerTag(result, TAG_TCY, data.getTcy());
        putLongTag(result, TAG_URLS, urlCount);
        putLongTag(result, TAG_INDEX_COUNT, indexCount);
    }

    public static class InnerElementWrapper<T> extends XmlDataWrapper<T> {
        private final String innerTagName;

        public InnerElementWrapper(T data, String name) {
            super(data);
            this.innerTagName = name;
        }

        @Override
        protected void doToXml(StringBuilder result) {
            if (data != null) {
                putTag(result, innerTagName, data.toString());
            }
        }
    }
}
