/* 
 Copyright (c) 2013 LDBC
 Linked Data Benchmark Council (http://www.ldbcouncil.org)
 
 This file is part of ldbc_snb_datagen.
 
 ldbc_snb_datagen is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 ldbc_snb_datagen is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with ldbc_snb_datagen.  If not, see <http://www.gnu.org/licenses/>.
 
 Copyright (C) 2011 OpenLink Software <bdsmt@openlinksw.com>
 All Rights Reserved.
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation;  only Version 2 of the License dated
 June 1991.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
package ldbc.snb.datagen.serializer;

import com.google.common.collect.ImmutableList;
import ldbc.snb.datagen.dictionary.Dictionaries;
import ldbc.snb.datagen.entities.dynamic.Forum;
import ldbc.snb.datagen.entities.dynamic.messages.Comment;
import ldbc.snb.datagen.entities.dynamic.messages.Photo;
import ldbc.snb.datagen.entities.dynamic.messages.Post;
import ldbc.snb.datagen.entities.dynamic.relations.ForumMembership;
import ldbc.snb.datagen.entities.dynamic.relations.Like;

import java.util.List;

import static ldbc.snb.datagen.serializer.FileName.*;

public class DynamicActivitySerializer extends LdbcSerializer {
    @Override
    public List<FileName> getFileNames() {
        return ImmutableList.of(FORUM, FORUM_HASMEMBER_PERSON, FORUM_HASTAG_TAG, PERSON_LIKES_POST,
                PERSON_LIKES_COMMENT, POST, POST_HASTAG_TAG, COMMENT, COMMENT_HASTAG_TAG);
    }

    @Override
    public void writeFileHeaders() {
        List<String> dates1 = ImmutableList.of("creationDate", "deletionDate", "explicitlyDeleted");

        List<String> dates2 = ImmutableList.of("creationDate", "deletionDate");

        writers.get(FORUM)                    .writeHeader(dates1, ImmutableList.of("id", "title", "ModeratorPersonId"));
        writers.get(FORUM_HASTAG_TAG)         .writeHeader(dates2, ImmutableList.of("ForumId", "TagId"));
        writers.get(FORUM_HASMEMBER_PERSON)   .writeHeader(dates1, ImmutableList.of("ForumId", "PersonId"));

        writers.get(POST)                     .writeHeader(dates1, ImmutableList.of("id", "imageFile", "locationIP", "browserUsed", "language", "content", "length", "CreatorPersonId", "ContainerForumId", "LocationCountryId"));
        writers.get(POST_HASTAG_TAG)          .writeHeader(dates2, ImmutableList.of("PostId", "TagId"));

        writers.get(COMMENT)                  .writeHeader(dates1, ImmutableList.of("id", "locationIP", "browserUsed", "content", "length", "CreatorPersonId", "LocationCountryId", "ParentPostId", "ParentCommentId"));
        writers.get(COMMENT_HASTAG_TAG)       .writeHeader(dates2, ImmutableList.of("CommentId", "TagId"));

        writers.get(PERSON_LIKES_POST)        .writeHeader(dates1, ImmutableList.of("PersonId", "PostId"));
        writers.get(PERSON_LIKES_COMMENT)     .writeHeader(dates1, ImmutableList.of("PersonId", "CommentId"));

    }

    public void serialize(final Forum forum) {
        List<String> dates = ImmutableList.of(formatDateTime(forum.getCreationDate()), formatDateTime(forum.getDeletionDate()), String.valueOf(forum.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, id, title, ModeratorPersonId
        writers.get(FORUM).writeEntry(dates, ImmutableList.of(
                Long.toString(forum.getId()),
                forum.getTitle(),
                Long.toString(forum.getModerator().getAccountId())
        ));

        List<String> dates2 = ImmutableList.of(formatDateTime(forum.getCreationDate()), formatDateTime(forum.getDeletionDate()));
        for (Integer i : forum.getTags()) {
            // creationDate, deletionDate, ForumId, TagId
            writers.get(FORUM_HASTAG_TAG).writeEntry(dates2, ImmutableList.of(
                    Long.toString(forum.getId()),
                    Integer.toString(i)
            ));
        }

    }

    public void serialize(final Post post) {
        List<String> dates1 = ImmutableList.of(formatDateTime(post.getCreationDate()), formatDateTime(post.getDeletionDate()), String.valueOf(post.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, id, imageFile, locationIP, browserUsed, language, content, length, CreatorPersonId, ContainerForumId, LocationCountryId
        writers.get(POST).writeEntry(dates1, ImmutableList.of(
                Long.toString(post.getMessageId()),
                "",
                post.getIpAddress().toString(),
                Dictionaries.browsers.getName(post.getBrowserId()),
                Dictionaries.languages.getLanguageName(post.getLanguage()),
                post.getContent(),
                Integer.toString(post.getContent().length()),
                Long.toString(post.getAuthor().getAccountId()),
                Long.toString(post.getForumId()),
                Integer.toString(post.getCountryId())
        ));

        List<String> dates2 = ImmutableList.of(formatDateTime(post.getCreationDate()), formatDateTime(post.getDeletionDate()));

        for (Integer t : post.getTags()) {
            // creationDate, deletionDate, PostId, TagId
            writers.get(POST_HASTAG_TAG).writeEntry(dates2, ImmutableList.of(
                    Long.toString(post.getMessageId()),
                    Integer.toString(t)
            ));
        }
    }

    public void serialize(final Comment comment) {
        List<String> dates1 = ImmutableList.of(formatDateTime(comment.getCreationDate()), formatDateTime(comment.getDeletionDate()), String.valueOf(comment.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, id, locationIP, browserUsed, content, length, CreatorPersonId, LocationCountryId, ParentPostId, ParentCommentId
        writers.get(COMMENT).writeEntry(dates1, ImmutableList.of(
                Long.toString(comment.getMessageId()),
                comment.getIpAddress().toString(),
                Dictionaries.browsers.getName(comment.getBrowserId()),
                comment.getContent(),
                Integer.toString(comment.getContent().length()),
                Long.toString(comment.getAuthor().getAccountId()),
                Integer.toString(comment.getCountryId()),
                comment.getParentMessageId() == comment.getRootPostId() ? Long.toString(comment.getRootPostId()) : "",
                comment.getParentMessageId() == comment.getRootPostId() ? "" : Long.toString(comment.getParentMessageId())
        ));

        List<String> dates2 = ImmutableList.of(formatDateTime(comment.getCreationDate()), formatDateTime(comment.getDeletionDate()));
        for (Integer t : comment.getTags()) {
            // creationDate, deletionDate, CommentId, TagId
            writers.get(COMMENT_HASTAG_TAG).writeEntry(dates2, ImmutableList.of(
                    Long.toString(comment.getMessageId()),
                    Integer.toString(t)
            ));
        }
    }

    public void serialize(final Photo photo) {
        List<String> dates1 = ImmutableList.of(formatDateTime(photo.getCreationDate()), formatDateTime(photo.getDeletionDate()), String.valueOf(photo.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, id, imageFile, locationIP, browserUsed, language, content, length, CreatorPersonId, ContainerForumId, LocationCountryId
        writers.get(POST).writeEntry(dates1, ImmutableList.of(
                Long.toString(photo.getMessageId()),
                photo.getContent(),
                photo.getIpAddress().toString(),
                Dictionaries.browsers.getName(photo.getBrowserId()),
                "",
                "",
                Integer.toString(0),
                Long.toString(photo.getAuthor().getAccountId()),
                Long.toString(photo.getForumId()),
                Integer.toString(photo.getCountryId())
        ));

        List<String> dates2 = ImmutableList.of(formatDateTime(photo.getCreationDate()), formatDateTime(photo.getDeletionDate()));
        for (Integer t : photo.getTags()) {
            // creationDate, deletionDate, PostId, TagId
            writers.get(POST_HASTAG_TAG).writeEntry(dates2, ImmutableList.of(
                    Long.toString(photo.getMessageId()),
                    Integer.toString(t)
            ));
        }
    }

    public void serialize(final ForumMembership membership) {
        List<String> dates = ImmutableList.of(formatDateTime(membership.getCreationDate()), formatDateTime(membership.getDeletionDate()), String.valueOf(membership.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, ForumId, PersonId
        writers.get(FORUM_HASMEMBER_PERSON).writeEntry(dates, ImmutableList.of(
                Long.toString(membership.getForumId()),
                Long.toString(membership.getPerson().getAccountId())
        ));
    }

    public void serialize(final Like like) {
        List<String> dates = ImmutableList.of(formatDateTime(like.getCreationDate()), formatDateTime(like.getDeletionDate()), String.valueOf(like.isExplicitlyDeleted()));

        // creationDate, deletionDate, explicitlyDeleted, PersonId, PostId
        // or
        // creationDate, deletionDate, explicitlyDeleted, PersonId, CommentId
        List<String> arguments = ImmutableList.of(
                Long.toString(like.getPerson()),
                Long.toString(like.getMessageId())
        );
        if (like.getType() == Like.LikeType.POST || like.getType() == Like.LikeType.PHOTO) {
            writers.get(PERSON_LIKES_POST).writeEntry(dates, arguments);
        } else {
            writers.get(PERSON_LIKES_COMMENT).writeEntry(dates, arguments);
        }
    }

    @Override
    protected boolean isDynamic() {
        return true;
    }

}
