package edu.ucsd.cse124;

import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.util.PriorityQueue;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Comparator;

public class TwitterHandler implements Twitter.Iface {
    protected Map<String,Account> accounts;
    protected Random rnd;
    public TwitterHandler() {
        this.rnd = new Random();
        this.accounts = new HashMap<String, Account>();
    }


    @Override
    public void ping() {
    }

    @Override
    public void createUser(String handle) throws AlreadyExistsException
    {
        if(accounts.containsKey(handle)){
            throw new AlreadyExistsException(handle);
        }
        accounts.put(handle, new Account(handle));
    }

    @Override
    public void subscribe(String handle, String theirhandle)
        throws NoSuchUserException
    {
        if(!accounts.containsKey(handle)) {
            throw new NoSuchUserException(handle);
        }

        if (!accounts.containsKey(theirhandle)) {
            throw new NoSuchUserException(theirhandle);
        }

        Account target = accounts.get(handle);
        if(!target.check_subscribed_accounts(theirhandle)){
            target.add_to_subscribed_accounts(theirhandle);
        }


    }

    @Override
    public void unsubscribe(String handle, String theirhandle)
        throws NoSuchUserException
    {
        if(!accounts.containsKey(handle)) {
            throw new NoSuchUserException(handle);
        }

        if (!accounts.containsKey(theirhandle)) {
            throw new NoSuchUserException(theirhandle);
        }

        Account target = accounts.get(handle);
        if(target.check_subscribed_accounts(theirhandle)){
            target.remove_to_subscribed_accounts(theirhandle);
        }
    }

    @Override
    public void post(String handle, String tweetString)
        throws NoSuchUserException, TweetTooLongException
    {
        if (tweetString.length() > 140) {
            throw new TweetTooLongException();
        }

        if(!accounts.containsKey(handle)){
            throw new NoSuchUserException(handle);
        }

        Account target = accounts.get(handle);

        Tweet new_tweet = new Tweet(
            (long)rnd.nextInt(Integer.MAX_VALUE),
            handle,
            System.currentTimeMillis(),
            0,
            tweetString
        );

        target.push_to_tweet_list(new_tweet);
    }

    @Override
    public List<Tweet> readTweetsByUser(String handle, int howmany)
        throws NoSuchUserException
    {
        if(!accounts.containsKey(handle)){
            throw new NoSuchUserException(handle);
        }
        Account target = accounts.get(handle);
        ArrayList<Tweet> alist = target.getTweetArrayList();
        List<Tweet>  output = new ArrayList<Tweet>(); 
        for(int i = alist.size()-1; i >= 0 && i >= (alist.size() - howmany); --i){
            output.add(alist.get(i));
        }
        return output;
    }

    //self-defined comparator for Tweet class
    public static Comparator<Tweet> timestanpComparator = new Comparator<Tweet>(){
        @Override
        public int compare(Tweet c1, Tweet c2) {
            return (int) (c2.posted - c1.posted);
        }
    };

    @Override
    public List<Tweet> readTweetsBySubscription(String handle, int howmany)
        throws NoSuchUserException
    {   
        if(!accounts.containsKey(handle)){
            throw new NoSuchUserException(handle);
        }
        Account target = accounts.get(handle);
        ArrayList<String> tarlist = target.get_subscribed_accounts();
        PriorityQueue<Tweet> priorityQ = new PriorityQueue<Tweet>(howmany, timestanpComparator);
        LinkedList<Tweet>  output = new LinkedList<Tweet>(); 
        ArrayList<Tweet> alist;
        Tweet tw;
        int count = 0;
        for(int j=0; j<tarlist.size(); ++j){
            alist = accounts.get(tarlist.get(j)).getTweetArrayList();
            for(int i=alist.size()-1; i>=0 && i>=(alist.size()-howmany); --i){
                tw = alist.get(i);
                if(count<howmany)
                    priorityQ.add(tw);
                else{
                    if( timestanpComparator.compare(tw,priorityQ.peek())>0 ){
                        priorityQ.poll();
                        priorityQ.add(tw);
                    }
                }
            }
        }
        for(int i = priorityQ.size() - 1; i >= 0; --i)
            output.addFirst(priorityQ.poll());
        return output;
    }

    @Override
    public void star(String handle, long tweetId) throws
        NoSuchUserException, NoSuchTweetException
    {
        if(!accounts.containsKey(handle)){
            throw new NoSuchUserException(handle);
        }

        Account target = accounts.get(handle);
        target.favoriting_tweet(tweetId);

    }
}

@@ -3644,24 +3644,25 @@
 accounts();%0A
+%0A
         Prio
@@ -3746,16 +3746,17 @@
 rator);%0A
+%0A
         
@@ -3841,16 +3841,17 @@
  alist;%0A
+%0A
         
@@ -3883,16 +3883,17 @@
 nt = 0;%0A
+%0A
         
@@ -3905,14 +3905,18 @@
 nt j
-=
+ = 
 0; j
-%3C
+ %3C 
 tarl
@@ -4024,17 +4024,19 @@
 or(int i
-=
+ = 
 alist.si
@@ -4048,18 +4048,22 @@
 1; i
+ 
 %3E=
+ 
 0 && i
+ 
 %3E=
+ 
 (ali
@@ -4151,17 +4151,19 @@
 ount
-%3C
+ %3C 
 howmany)
 %0A   
@@ -4150,32 +4150,62 @@
 count %3C howmany)
+%7B%0A                    count++;
 %0A               
@@ -4220,32 +4220,50 @@
 orityQ.add(tw);%0A
+                %7D%0A
                 
@@ -4323,16 +4323,17 @@
 pare(tw,
+ 
 priority
@@ -4341,16 +4341,17 @@
 .peek())
+ 
 %3E0 )%7B%0A  
@@ -4489,32 +4489,33 @@
     %7D%0A        %7D%0A
+%0A
         for(int 
@@ -4556,55 +4556,149 @@
 --i)
-%0A            output.addFirst(priorityQ.poll());
+%7B%0A            Tweet temp = priorityQ.poll();%0A            System.out.println(temp);%0A%0A            output.addFirst(temp);            %0A        %7D%0A
 %0A   

change client