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

import com.google.common.collect.Iterables;
import ru.yandex.webmaster3.core.semantic.review_business.model.Author;
import ru.yandex.webmaster3.core.semantic.review_business.model.Social;

import java.util.*;

import static com.google.common.collect.Lists.newArrayList;

/**
 * Immutable implementation of {@link Author}
 * that on each modification call returns new instance.
 * <p/>
 * User: willzyx
 * Date: 3/30/12 - 4:44 PM
 */
public class AuthorWrapper extends Author {

    /**
     * Static factory.
     * This method should be used
     * for obtain instance of wrapper
     * for further manipulations.
     *
     * @return instance of AuthorWrapper over empty Author
     */
    public static AuthorWrapper newAuthor() {
        return EMPTY_AUTHOR_WRAPPER;
    }

    private final Author author;

    public AuthorWrapper(Author author) {
        this.author = author;
    }

    @Override
    public String getFn() {
        return author.getFn();
    }

    public AuthorWrapper setFn(final String fn) {
        return new AuthorWrapper(this) {
            @Override
            public String getFn() {
                return fn;
            }
        };
    }

    @Override
    public String getLogin() {
        return author.getLogin();
    }

    public AuthorWrapper setLogin(final String login) {
        return new AuthorWrapper(this) {
            @Override
            public String getLogin() {
                return login;
            }
        };
    }

    @Override
    public String getDisplayName() {
        return author.getDisplayName();
    }

    @Deprecated
    public AuthorWrapper setDisplayName(final String displayName) {
        return new AuthorWrapper(this) {
            @Override
            public String getDisplayName() {
                return displayName;
            }
        };
    }

    @Override
    public SignPrivacy getSignPrivacy() {
        return author.getSignPrivacy();
    }

    public AuthorWrapper setSignPrivacy(final Author.SignPrivacy signPrivacy) {
        return new AuthorWrapper(this) {
            @Override
            public SignPrivacy getSignPrivacy() {
                return signPrivacy;
            }
        };
    }

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

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

    @Override
    public String getEmail() {
        return author.getEmail();
    }

    public AuthorWrapper setEmail(final String email) {
        return new AuthorWrapper(this) {
            @Override
            public String getEmail() {
                return email;
            }
        };
    }

    @Override
    public String getAvatarUrl() {
        return author.getAvatarUrl();
    }

    public AuthorWrapper setAvatarUrl(final String avatarUrl) {
        return new AuthorWrapper(this) {
            @Override
            public String getAvatarUrl() {
                return avatarUrl;
            }
        };
    }

    @Override
    public Integer getThanksCount() {
        return author.getThanksCount();
    }

    public AuthorWrapper setThanksCount(final Integer thanksCount) {
        return new AuthorWrapper(this) {
            @Override
            public Integer getThanksCount() {
                return thanksCount;
            }
        };
    }

    @Override
    public Integer getPostsCount() {
        return author.getPostsCount();
    }

    public AuthorWrapper setPostsCount(final Integer postsCount) {
        return new AuthorWrapper(this) {
            @Override
            public Integer getPostsCount() {
                return postsCount;
            }
        };
    }

    @Override
    public Integer getCommentsCount() {
        return author.getCommentsCount();
    }

    public AuthorWrapper setCommentsCount(final Integer commentsCount) {
        return new AuthorWrapper(this) {
            @Override
            public Integer getCommentsCount() {
                return commentsCount;
            }
        };
    }

    @Override
    public Integer getFriendsCount() {
        return author.getFriendsCount();
    }

    public AuthorWrapper setFriendsCount(final Integer friendsCount) {
        return new AuthorWrapper(this) {
            @Override
            public Integer getFriendsCount() {
                return friendsCount;
            }
        };
    }

    @Override
    public Float getKarma() {
        return author.getKarma();
    }

    public AuthorWrapper setKarma(final Float karma) {
        return new AuthorWrapper(this) {
            @Override
            public Float getKarma() {
                return karma;
            }
        };
    }

    @Override
    public Date getRegdate() {
        return author.getRegdate();
    }

    public AuthorWrapper setRegdate(final Date regdate) {
        return new AuthorWrapper(this) {
            @Override
            public Date getRegdate() {
                return regdate;
            }
        };
    }

    @Override
    public Collection<Social> getSocials() {
        return author.getSocials();
    }

    public AuthorWrapper setSocials(final Collection<Social> social) {
        return new AuthorWrapper(this) {
            @Override
            public Collection<Social> getSocials() {
                return Collections.unmodifiableCollection(social);
            }
        };
    }

    public AuthorWrapper addSocials(final Social... social) {
        return addSocials(newArrayList(social));
    }

    @SuppressWarnings("unchecked")
    public AuthorWrapper addSocials(final Collection<Social> social) {
        return new AuthorWrapper(this) {
            @Override
            public Collection<Social> getSocials() {
                return Collections.unmodifiableCollection(newArrayList(Iterables.concat(super.getSocials(), social)));
            }
        };
    }

    public AuthorWrapper setSocials(final Social... social) {
        return setSocials(newArrayList(social));
    }


    private static final AuthorWrapper EMPTY_AUTHOR_WRAPPER = new AuthorWrapper(
            new Author() {
                @Override
                public String getFn() {
                    return null;
                }

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

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

                @Override
                public SignPrivacy getSignPrivacy() {
                    return SignPrivacy.NAME;
                }

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

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

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

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

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

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

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

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

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

                @Override
                public Collection<Social> getSocials() {
                    return Collections.emptyList();
                }
            }
    );
}
