%matplotlib notebook
%load_ext autoreload
%autoreload 2

import matplotlib.pyplot as plt
import os
import datetime
import pandas as pd
import seaborn as sns
import numpy as np
import sys
sys.path.append(os.path.join(os.getcwd(), "src"))

import util.io as mio
from util import statsUtil
import util.plotting as mplot
from model.conversationDataframe import ConversationDataframe
from stats.iConvStats import IConvStats

sns.set_context("paper")
sns.set_style("darkgrid")

# filepath to your conversation file. You can use my conversations examples for testing
FILEPATH = "src/resources/unittest/test_plotting.txt"
conv = ConversationDataframe(FILEPATH)
conv.loadMessages()

"""
Explanation: Table of Contents

Intro
Interval Stats
Basic length stats
By Sender
By Year and Month
By Hour
By Day


Lexical Stats
By Sender
By Year and Month
By Hour


Emoticons Stats
Interactive Visualization

Intro
This notebook explores the basic conversation stats together with their visualization.
End of explanation
"""


start, end, interval = conv.stats.getIntervalStats()
days = conv.stats.getDaysWithoutMessages()
print("Conversation started: {}".format(str(start)))
print("Conversation ended: {}".format(str(end)))
print("Conversation overall duration: {}".format(interval))

percentage = (len(days)/(interval.days+1))*100
print("{:.0f} days without messages ({:.2f}% of the total days duration)".format(len(days), percentage))

"""
Explanation: Interval Stats
End of explanation
"""


basicLengthStats = conv.stats.generateStats(IConvStats.STATS_NAME_BASICLENGTH)
basicLengthStats

"""
Explanation: Basic Length Stats
Aggregated stats for the following metrics:
* number of messages (each messanger bubble is a separate message)
* total length of messages (in number of characters, special ones included)
* message average length (averaging total length by number of messages)
By Sender
End of explanation
"""


month_basic_stats = conv.stats.generateStatsByYearAndMonth(IConvStats.STATS_NAME_BASICLENGTH, stackStats=True)

mplot.plotBasicLengthStatsByYearAndMonth(month_basic_stats, 
                                         targetSenders=['s1','s2'], 
                                         targetStats=['lenMsgs'],
                                        yearsToShow=None)

"""
Explanation: By Year and Month
End of explanation
"""


hours_basic_stats = conv.stats.generateStatsByHour(IConvStats.STATS_NAME_BASICLENGTH, stackStats=True)

mplot.plotBasicLengthStatsByHour(hours_basic_stats, 
                                 targetSenders=['s1','s2'], 
                                 targetStats=['lenMsgs'])

"""
Explanation: By Hour
End of explanation
"""


day_basic_stats = conv.stats.generateStatsByYearMonthDay(IConvStats.STATS_NAME_BASICLENGTH)

mplot.plotSingleBasicLengthStatHeatmap(day_basic_stats, 'lenMsgs', 'total', ['2014','2015'])

df = statsUtil.dateRangeTransform(day_basic_stats, {'sender':['total'], 'stat':['numMsgs']})

df.plot()

"""
Explanation: By Day
End of explanation
"""


lexicalStats = conv.stats.generateStats(IConvStats.STATS_NAME_LEXICAL)
lexicalStats

"""
Explanation: Lexical Stats
Tokens count and vocabulary. Tokens count consider also duplicate words, while vocabulary (also called types) is the count of unique words. Lexical richness/diversity is the ratio between vocabulary and tokens count.
By Sender
End of explanation
"""


month_lexical_stats = conv.stats.generateStatsByYearAndMonth(IConvStats.STATS_NAME_LEXICAL)

mplot.plotRichnessVariation(month_lexical_stats, 'month', yearsToShow=['2014', '2015'])

"""
Explanation: By Year and Month
End of explanation
"""


hour_lexical_stats = conv.stats.generateStatsByHour(IConvStats.STATS_NAME_LEXICAL, stackStats=True)

mplot.plotBasicLengthStatsByHour(hour_lexical_stats, targetStats=['lexicalRichness'], kind='point')

"""
Explanation: By Hour
End of explanation
"""


emoticons_stats = conv.stats.generateStats(IConvStats.STATS_NAME_EMOTICONS)
emoticons_stats

"""
Explanation: Emoticons Stats
End of explanation
"""


from ipywidgets import interact, widgets

import matplotlib.pyplot as plt
from IPython.display import display, clear_output

%matplotlib inline

hours_basic_stats = conv.stats.generateStatsByYearAndHour(IConvStats.STATS_NAME_BASICLENGTH, stackStats=True)

years = list(map(int, hours_basic_stats['year'].unique()))

@interact(sender=list(map(str, hours_basic_stats['sender'].unique())), 
          stat=list(map(str, hours_basic_stats['stat'].unique())), 
          #year=list(map(str, hours_basic_stats['year'].unique())))
          year=(years[0], years[-1]))
def myplot(sender, stat, year):
    mplot.plotSingleBasicLengthStatByYearAndHour(hours_basic_stats, stat, 
                                                 yearsToShow=[str(year)],
                                                targetSenders=[sender])
    sns.plt.show()

class Dashboard():
    def __init__(self, data):
        self.data = data
        self.selectors = {}
        
    def create_selector(self, target_col, description):
        selector = widgets.SelectMultiple(
            options = list(map(str, self.data[target_col].unique())),
            description = description
        )
        self.selectors[target_col] = selector
        
    def get_selector_values(self, selector_key):
        return list(self.selectors[selector_key].value)
    
    def run(self, fun):
        for k, selector in self.selectors.items():
            selector.observe(fun, names='value')
            display(selector)

d = Dashboard(hours_basic_stats)
d.create_selector('year', 'Year:')
d.create_selector('sender', 'Sender:')

def my_plot(x):
    sns.plt.clf()
    mplot.plotSingleBasicLengthStatByYearAndHour(hours_basic_stats, 'lenMsgs', 
                                                 yearsToShow=d.get_selector_values('year'),
                                                targetSenders=d.get_selector_values('sender'))

d.run(my_plot)

"""
Explanation: Interactive Visualization [WIP]
End of explanation
"""


