#' Función que dado un determinado corpus lo tokeniza y limpia el texto quitándole símbolos, puntuaciones,
#' urls, números, hashtags, menciones, repeticiones de vocales de tres veces o más y remueve las
#' stopwords.
#' 
#' @param corpus corpus a tokenizar
#' 
#' @return conjunto de tokens relacionados a cada texto del corpus
#'
clean_and_generate_tokens <- function(corpus){
  remove_stopwords <- c(stopwords("spanish")[stopwords("spanish") != "no"], "etc", "q", "i", "d") #I+D 

  toks <- as.character(corpus) %>%
    char_tolower() %>% 
    str_replace_all("\\(.*\\)","'") %>%
    tokens(remove_url = TRUE, remove_punct = TRUE, remove_symbols = TRUE, remove_numbers = TRUE, split_hyphens = TRUE) %>% 
    tokens_remove(pattern = "#\\w+|@\\w+|[^[:alpha:] ]+|[a|e|i|o|u]{3,30}", valuetype = "regex") %>% 
    tokens_remove(remove_stopwords) %>% 
    tokens_wordstem() 
  
  return(toks)
}

#' Función que dado un determinado conjunto de tokens crea su matriz de documentos-características con un mínimo 
#' por carácteres de dos y un mínimo de frecuencia entre los términos de 10.
#' 
#' @param tokens conjunto de tokens que convertir en dfm
#' 
#' @return matriz dfm
#'
clean_dfm <- function(tokens){
  dfm_toks <- tokens %>%
    dfm() %>%
    dfm_keep(min_nchar = 2) %>% #ponemos de manifiesto que mínimo las palabras deben de tener dos carácteres
    dfm_trim(min_termfreq = 10) #quitamos los términos que tengan una frecuencia inferior a 10
  
  return(dfm_toks)
}

#' Compara las características del grupo en el dfm pasado por parámetro contra todas las características
#' 
#' @param dfm matrix dfm
#' @param group agrupación sobre el dfm
#' 
#' @return dataframe con las características, sus valores de chi2 y p y el número de ocurrencias.
#'
getKeyness <- function(dfm, group){
  tstat_key <- quanteda.textstats::textstat_keyness(dfm, target = group)
  return(tstat_key)
}

#' Función que devuelve la frecuencia de términos de la evaluación (evaluate) pasa por párametro
#' 
#' @param dfm matrix dfm
#' @param evaluate condición del dfm
#' 
#' @return data.frame con la característica, su frecuencia, rango de la característica, 
#' frecuencia del documento de la característica y la etiqueta del grupo.
#'
getFreqWord <- function(dfm, evaluate){
  return(quanteda.textstats::textstat_frequency(dfm[evaluate, ]))
}

#' Función que calcula el sentimiento de las palabras por texto definidas en un dfm. 
#' 
#' @param dfm matrix dfm
#' @param dict diccionario de palabras, definiéndolas como positivas, neutras y negativas
#' @param fun función que utilizará el método text_stat_polarity (sent_logit, sent_abspropdiff o sent_relpropdiff)
#' 
#' 
#' @return data.frame con el sentimiento de cada texto
#'
getSentiment <- function(dfm, dict, fun){
  sentiment <- dfm %>% 
    quanteda.sentiment::textstat_polarity(dictionary = dict, fun = fun) %>%
    mutate(sentiment = replace_na(sentiment, 0.0)) 
  
  return(sentiment)
}

#' Función que une las columnas sent y corp y que recoge las variables (sentiment, location, clasify, created_at)
#' y calcula su polaridad en función del sentimiento encontrado
#' 
#' @param sent data.frame con el sentimiento por texto
#' @param corp corpus
#' 
#' @return data.frame con el sentimiento, la localización, la clasificación, la fecha de creación y
#' la polaridad de cada texto
#'
getPolarity <- function(sent, corp){
  sentpol <- cbind(sent, corp) %>% 
  select(sentiment, location, clasify, created_at) %>% 
  mutate(polarity = ifelse(sentiment > 0.0, "positive", ifelse(sentiment < 0.0, "negative", "neutral")))
  
  return(sentpol)  
}

#' Función que calcula el sentimiento y la polaridad de un dfm.
#' 
#' @param dfm matrix dfm
#' @param dict diccionario de palabras, definiéndolas como positivas, neutras y negativas
#' @param fun función que utilizará el método text_stat_polarity (sent_logit, sent_abspropdiff o sent_relpropdiff)
#' @param corp corpus
#' 
#' @return data.frame con el sentimiento, la localización, la clasificación, la fecha de creación y
#' la polaridad de cada texto.
#'
getSentimentPolarity <- function(dfm, dict, fun, corp){
  sent <- getSentiment(dfm, dict, fun)
  sentpol <- getPolarity(sent, corp)
  return(sentpol)  
}

#' Función que calcula la media del sentimiento agrupada por fecha de creación y clasificación.
#' 
#' @param sent data.frame con el sentimientola clasificación y la fecha de creación de cada texto.
#' 
#' @return data.frame con la media del sentimiento, la fecha de creación y la clasificación de cada texto.
#'
meanSentiment <- function(sent){
  meanSentiment <- sent %>% 
    mutate(created_at = format(created_at, "%m-%d")) %>%
    group_by(created_at, clasify) %>% 
    summarize(mean_sentiment = sum(sentiment)/n())
  return(meanSentiment)
}