package ikube.action.index.handler.internet;

import com.google.gson.Gson;
import ikube.IConstants;
import ikube.action.index.IndexManager;
import ikube.action.index.handler.IResourceProvider;
import ikube.model.IndexableTweets;
import ikube.toolkit.FileUtilities;
import ikube.toolkit.SerializationUtilities;
import ikube.toolkit.ThreadUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.social.twitter.api.*;
import org.springframework.social.twitter.api.impl.TwitterTemplate;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * This class will use the Spring social module to get tweets from Twitter, at a rate of around 1% of the tweets.
 *
 * @author Michael Couck
 * @version 01.00
 * @since 19.06.13
 */
class TwitterResourceProvider implements IResourceProvider<Tweet>, StreamListener {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private int clones;
    private Stack<Tweet> tweets;

    /**
     * The directories where the stack will be persisted to the file system.
     */
    private File tweetsDirectory;

    /**
     * Constructor takes the configuration for the Twitter account, and initializes the streaming classes that will accept the Twitter data.
     *
     * @param indexableTweets the configuration for the Twitter account, importantly the OAuth login details
     * @throws IOException
     */
    TwitterResourceProvider(final IndexableTweets indexableTweets) throws IOException {
        clones = indexableTweets.getClones();
        tweets = new Stack<>();
        tweetsDirectory = FileUtilities.getOrCreateDirectory(new File(IConstants.ANALYTICS_DIRECTORY, "tweets"));
        TwitterTemplate twitterTemplate = new TwitterTemplate( //
            indexableTweets.getConsumerKey(), //
            indexableTweets.getConsumerSecret(), //
            indexableTweets.getToken(), //
            indexableTweets.getTokenSecret());
        StreamingOperations streamingOperations = twitterTemplate.streamingOperations();
        StreamListener streamListener = this;
        List<StreamListener> listeners = Arrays.asList(streamListener);
        streamingOperations.sample(listeners);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized Tweet getResource() {
        while (tweets.isEmpty()) {
            try {
                wait(1000);
            } catch (InterruptedException e) {
                logger.error(null, e);
            } catch (Exception e) {
                logger.error(null, e);
                return null;
            }
        }
        return tweets.pop();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void setResources(final List<Tweet> tweets) {
        if (tweets != null) {
            this.tweets.addAll(tweets);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onTweet(final Tweet tweet) {
        persistResources(tweet);
        if (tweets.size() < IConstants.MILLION) {
            tweets.push(tweet);
            if (this.clones > 0) {
                int clones = this.clones;
                do {
                    Tweet clone = (Tweet) SerializationUtilities.clone(tweet);
                    tweets.push(clone);
                } while (--clones > 0);
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onLimit(final int numberOfLimitedTweets) {
        logger.info("Tweets limited : " + numberOfLimitedTweets);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onDelete(final StreamDeleteEvent deleteEvent) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void onWarning(final StreamWarningEvent warnEvent) {
        logger.info("Tweet warning : " + warnEvent.getCode());
    }

    void persistResources(final Tweet... tweets) {
        try {
            File latestDirectory = IndexManager.getLatestIndexDirectory(tweetsDirectory, null);
            if (latestDirectory == null) {
                latestDirectory = FileUtilities.getOrCreateDirectory(new File(tweetsDirectory, Long.toString(System.currentTimeMillis())));
            } else {
                String[] files = latestDirectory.list();
                if (files != null && files.length > 10000) {
                    latestDirectory = FileUtilities.getOrCreateDirectory(new File(tweetsDirectory, Long.toString(System.currentTimeMillis())));
                }
            }
            Gson gson = new Gson();
            for (final Tweet tweet : tweets) {
                String string = gson.toJson(tweet);
                File output = new File(latestDirectory, Long.toString(System.currentTimeMillis()) + ".json");
                File outputFile = FileUtilities.getOrCreateFile(output);
                FileUtilities.setContents(outputFile, string.getBytes());
                ThreadUtilities.sleep(1);
            }
        } catch (Exception e) {
            logger.error(null, e);
        }
    }

}
@@ -101,49 +101,8 @@
 s;%0D%0A
-import ikube.action.index.IndexManager;%0D%0A
 impo
@@ -2492,16 +2492,22 @@
  catch (
+final 
 Interrup
@@ -2578,32 +2578,38 @@
        %7D catch (
+final 
 Exception e) %7B%0D%0A
@@ -3987,24 +3987,67 @@
 ;%0D%0A    %7D%0D%0A%0D%0A
+    Stack%3CTweet%3E stack = new Stack%3C%3E();%0D%0A%0D%0A
     void per
@@ -4098,151 +4098,39 @@
     
-try %7B%0D%0A            File latestDirectory = IndexManager.getLatestIndexDirectory(tweetsDirectory, null);%0D%0A            if (latestDirectory == null
+for (final Tweet tweet : tweets
 ) %7B%0D
@@ -4146,275 +4146,90 @@
     
-    
-latestDirectory = FileUtilities.getOrCreateDirectory(new File(tweetsDirectory, Long.toString(System.currentTimeMillis())));%0D%0A            %7D else %7B%0D%0A                String%5B%5D files = latestDirectory.list();%0D%0A                if (files != null && files.length %3E 10000)
+stack.add(tweet);%0D%0A        %7D%0D%0A        if (stack.size() %3E 10000) %7B%0D%0A            try
  %7B%0D%0A
@@ -4244,19 +4244,20 @@
         
-   
+File
  latestD
@@ -4382,38 +4382,8 @@
     
-            %7D%0D%0A            %7D%0D%0A
     
@@ -4411,24 +4411,28 @@
 ew Gson();%0D%0A
+    
             
@@ -4452,35 +4452,38 @@
 eet tweet : 
-tweets
+stack
 ) %7B%0D%0A
+    
             
@@ -4531,32 +4531,36 @@
                 
+   
+ 
 File output = ne
@@ -4646,32 +4646,36 @@
                 
+    
 File outputFile 
@@ -4728,24 +4728,28 @@
             
+  
+  
 FileUtilitie
@@ -4811,16 +4811,20 @@
         
+    
 ThreadUt
@@ -4846,35 +4846,43 @@
 );%0D%0A            
+  
+  
 %7D%0D%0A
+    
         %7D catch 
@@ -4902,32 +4902,36 @@
  %7B%0D%0A            
+  
+  
 logger.error(nul
@@ -4930,32 +4930,75 @@
 rror(null, e);%0D%0A
+            %7D%0D%0A            stack.clear();%0D%0A
         %7D%0D%0A    %7D

Fine tuning the general operations.