package ru.yandex.wmconsole.data.sitemaps;

import java.util.Comparator;

import ru.yandex.common.util.db.OrderByClause;
import ru.yandex.wmconsole.data.info.SitemapInfo;

/**
 * @author ailyin
 */
public class SitemapInfoComparator implements Comparator<SitemapInfo> {
    private final SitemapInfoSortBy sitemapInfoSortBy;

    private final boolean ascending;

    public SitemapInfoComparator(OrderByClause order) {
        this.sitemapInfoSortBy = SitemapInfoSortBy.getByArgument(order.getColumnName());
        this.ascending = order.isAscending();
    }

    @Override
    public int compare(SitemapInfo info1, SitemapInfo info) {
        return sitemapInfoSortBy.compare(info1, info) * (ascending ? 1 : -1);
    }

    private enum SitemapInfoSortBy {
        URL("url") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                return info1.getUrl().compareTo(info.getUrl());
            }
        },
        SUBMITTED_ON("submitted-on") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                return info1.getSubmittedDate().compareTo(info.getSubmittedDate());
            }
        },
        FROM_ROBOTS_TXT("from-robots-txt") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                return compareBooleans(info1.isFromRobotsTxt(), info.isFromRobotsTxt());
            }
        },
        FROM_USER("from-user") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                return compareBooleans(info1.isFromUser(), info.isFromUser());
            }
        },
        PROCESSED_ON("processed-on") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                if (info1.getProccessedDate() == null) {
                    return (info.getProccessedDate() == null) ? 0 : -1;
                } else if (info.getProccessedDate() == null) {
                    return 1;
                } else {
                    return info1.getProccessedDate().compareTo(info.getProccessedDate());
                }
            }
        },
        FORMAT("format") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                if (info1.getSitemapFormat() == null) {
                    return (info.getSitemapFormat() == null) ? 0 : -1;
                } else if (info.getSitemapFormat() == null) {
                    return 1;
                } else {
                    return info1.getSitemapFormat().compareTo(info.getSitemapFormat());
                }
            }
        },
        URL_COUNT("url-count") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                if (info1.getUrlsCount() == null) {
                    return (info.getUrlsCount() == null) ? 0 : -1;
                } else if (info.getUrlsCount() == null) {
                    return 1;
                } else {
                    return info1.getUrlsCount().compareTo(info.getUrlsCount());
                }
            }
        },
        ERROR_COUNT("error-count") {
            @Override
            protected int compare(SitemapInfo info1, SitemapInfo info) {
                if (info1.getXmlErrorsCount() == null) {
                    return (info.getXmlErrorsCount() == null) ? 0 : -1;
                } else if (info.getXmlErrorsCount() == null) {
                    return 1;
                } else {
                    return info1.getXmlErrorsCount().compareTo(info.getXmlErrorsCount());
                }
            }
        };

        private static final SitemapInfoSortBy DEFAULT_SORT_BY = URL;

        private String arg;

        SitemapInfoSortBy(String arg) {
            this.arg = arg;
        }

        public static SitemapInfoSortBy getByArgument(String arg) {
            for (SitemapInfoSortBy sortBy : SitemapInfoComparator.SitemapInfoSortBy.values()) {
                if (sortBy.arg.equals(arg)) {
                    return sortBy;
                }
            }

            return DEFAULT_SORT_BY;
        }

        protected abstract int compare(SitemapInfo info1, SitemapInfo info);

        protected int compareBooleans(boolean b1, boolean b2) {
            if (b1 == b2) {
                return 0;
            } else if (b2) {
                return -1;
            } else {
                return 1;
            }
        }
    }
}
