package org.crunchytorch.coddy.snippet.service;

import org.crunchytorch.coddy.application.data.Page;
import org.crunchytorch.coddy.application.exception.EntityNotFoundException;
import org.crunchytorch.coddy.application.service.AbstractService;
import org.crunchytorch.coddy.snippet.elasticsearch.entity.SnippetEntity;
import org.crunchytorch.coddy.snippet.elasticsearch.query.BoolOperand;
import org.crunchytorch.coddy.snippet.elasticsearch.query.SnippetQueryFieldBuilder;
import org.crunchytorch.coddy.snippet.elasticsearch.query.field.KeywordsFieldBuilder;
import org.crunchytorch.coddy.snippet.elasticsearch.query.field.TitleFieldBuilder;
import org.crunchytorch.coddy.snippet.elasticsearch.repository.SnippetRepository;
import org.crunchytorch.coddy.user.data.security.JWTPrincipal;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.ws.rs.core.SecurityContext;
import java.util.Date;
import java.util.stream.Stream;

@Service
public class SnippetService extends AbstractService<SnippetEntity> {

    @Autowired
    public SnippetService(SnippetRepository repository) {
        super(repository);
    }

    public SnippetEntity getSnippet(String id) {
        SnippetEntity entity = this.repository.findOne(id);

        if (entity == null) {
            throw new EntityNotFoundException("snippet with the id : " + id + " not found");
        }

        return entity;
    }

    public SnippetEntity create(SnippetEntity entity, SecurityContext securityContext) {
        entity.setId(null);
        // Set date to now
        Date now = new Date();
        entity.setCreated(now);
        entity.setLastModified(now);
        // Set author from token information
        entity.setAuthor(((JWTPrincipal) securityContext.getUserPrincipal()).getLogin());
        // Initiate rate
        entity.setRate(0);
        return super.create(entity);
    }

    public SnippetEntity update(SnippetEntity snippetUpdated) {
        SnippetEntity oldSnippet = this.getSnippet(snippetUpdated.getId());
        return super.create(new SnippetEntity(snippetUpdated, oldSnippet));
    }

    /**
     * @param words : a list of word separate by space
     * @param from  : the offset from the first result you want to fetch
     * @param size  : allows you to configure the maximum amount of hits to be returned
     * @return a page with the result of the research and the number of entity found.
     */
    public Page<SnippetEntity> search(String words, int from, int size) {
        SnippetQueryFieldBuilder<TitleFieldBuilder> titleBuilder =
                new TitleFieldBuilder()
                        .addWord(words)
                        .setOperand(BoolOperand.OR)
                        .buildQuery();

        SnippetQueryFieldBuilder<KeywordsFieldBuilder> keywordsBuilder =
                new KeywordsFieldBuilder();

        Stream.of(words.split(" ")).forEach(keywordsBuilder::addWord);

        keywordsBuilder
                .setOperand(BoolOperand.OR)
                .buildQuery();

        return this.search(from, size, keywordsBuilder, titleBuilder);
    }

    private Page<SnippetEntity> search(int from, int size, SnippetQueryFieldBuilder... queryFieldBuilders) {
        final Pageable page = new PageRequest(from, size);
        final BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        Stream.of(queryFieldBuilders).forEach(snippetQueryFieldBuilder -> snippetQueryFieldBuilder.appendQueryBuilder(queryBuilder));

        return new Page<>(this.repository.search(queryBuilder, page));
    }

    /**
     * This method will delete the {@link SnippetEntity snippet} from the given ID.
     *
     * @param id the snippet's ID
     * @throws EntityNotFoundException if the given ID is not associated to a {@link SnippetEntity snippet}
     */
    public void delete(final String id) {
        super.delete(this.getSnippet(id));
    }
}

@@ -317,79 +317,8 @@
 ty;%0A
-import org.crunchytorch.coddy.snippet.elasticsearch.query.BoolOperand;%0A
 impo
@@ -2637,33 +2637,8 @@
     
-SnippetQueryFieldBuilder%3C
 Titl
@@ -2650,17 +2650,16 @@
 dBuilder
-%3E
  titleBu
@@ -2767,35 +2767,29 @@
            .
+u
 se
-tOperand(
+Or
 BoolOperand.
@@ -2779,35 +2779,33 @@
 useOrBoolOperand
-.OR
+(
 )%0A              
@@ -2842,33 +2842,8 @@
     
-SnippetQueryFieldBuilder%3C
 Keyw
@@ -2858,17 +2858,16 @@
 dBuilder
-%3E
  keyword
@@ -3039,19 +3039,13 @@
    .
+u
 se
-tOperand(
+Or
 Bool
@@ -3055,11 +3055,9 @@
 rand
-.OR
+(
 )%0A  

use instance as type directly