# Copyright (C) Tal Galili
#
# This file is part of dendextend.
#
# dendextend is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# dendextend is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
#  A copy of the GNU General Public License is available at
#  http://www.r-project.org/Licenses/
#







#' @title Tries to run DendSer on a dendrogram
#' @export
#' @description
#' Implements dendrogram seriation.
#' The function tries to turn the dend into hclust, on 
#' which it runs \link[DendSer]{DendSer}.
#' 
#' Also, if a distance matrix is missing, it will try
#' to use the \link{cophenetic} distance.
#' @param dend An object of class dendrogram
#' @param ser_weight Used by cost function to evaluate
#'  ordering. For cost=costLS, this is a vector of
#'   object weights. Otherwise is a dist or symmetric matrix.
#' passed to DendSer.
#' If it is missing, the cophenetic distance is used instead.
#' @param ... parameters passed to \link[DendSer]{DendSer}
#' @return Numeric vector giving an optimal dendrogram order
#' @seealso \code{\link[DendSer]{DendSer}}, \link{DendSer.dendrogram} ,
#' \link{untangle_DendSer}, \link{rotate_DendSer} 
#' @examples
#' \dontrun{
#' library(DendSer) # already used from within the function
#' hc <- hclust(dist(USArrests[1:4,]), "ave")
#' dend <- as.dendrogram(hc)
#' DendSer.dendrogram(dend)
#' }
DendSer.dendrogram <- function(dend, ser_weight, ...) {
   h <- as.hclust(dend)
   if(missing(ser_weight)) ser_weight <- cophenetic(dend)
   # library(DendSer)
   DendSer::DendSer(h = h, ser_weight = ser_weight,...)
}


#' @title Rotates dend based on DendSer
#' @export
#' @description
#' Rotates a dendrogram based on its seriation
#' 
#' The function tries to turn the dend into hclust using
#' \link{DendSer.dendrogram} (based on \link[DendSer]{DendSer})
#' 
#' Also, if a distance matrix is missing, it will try
#' to use the \link{cophenetic} distance.
#' @param dend An object of class dendrogram
#' @param ser_weight Used by cost function to evaluate
#'  ordering. For cost=costLS, this is a vector of
#'   object weights. Otherwise is a dist or symmetric matrix.
#' passed to \link{DendSer.dendrogram} and from
#' there to \link[DendSer]{DendSer}.
#' 
#' If it is missing, the cophenetic distance is used instead.
#' @param ... parameters passed to \link[DendSer]{DendSer}
#' @return Numeric vector giving an optimal dendrogram order
#' @seealso \code{\link[DendSer]{DendSer}}, \link{DendSer.dendrogram} ,
#' \link{untangle_DendSer}, \link{rotate_DendSer} 
#' @examples
#' \dontrun{
#' library(DendSer) # already used from within the function

#' dend <- USArrests[1:4,] %>% dist %>% hclust("ave") %>% as.dendrogram
#' DendSer.dendrogram(dend)
#' 
#' tanglegram(dend, rotate_DendSer(dend))
#' 
#' }
rotate_DendSer <- function(dend, ser_weight, ...) {
   ord <- tryCatch(DendSer.dendrogram(dend, ser_weight = ser_weight), error = function(e) seq_len(nleaves(dend)))
   #    print(ord)
   rotate(dend, ord)
}

#' @title Tries to run DendSer on a dendrogram
#' @export
#' @description
#' The function tries to turn the dend into hclust.
#' It then uses the \link{cophenetic} distance matrix
#' for optimizing the tree's rotation.
#' 
#' This is a good (and fast) starting point for link{untangle_step_rotate_2side}
#' @param dend An object of class \link{dendlist}
#' @param ... NOT USED
#' @return A dendlist object with ordered dends
#' @seealso \code{\link[DendSer]{DendSer}}, \link{DendSer.dendrogram} ,
#' \link{untangle_DendSer}, \link{rotate_DendSer} 
#' @examples
#' \dontrun{
#' set.seed(232)
#' ss <- sample(1:150, 20)
#' dend1 <- iris[ss,-5] %>% dist %>% hclust("com") %>% as.dendrogram
#' dend2 <- iris[ss,-5] %>% dist %>% hclust("sin") %>% as.dendrogram
#' dend12 <- dendlist(dend1, dend2)
#' 
#' # bad solutions
#' dend12 %>% tanglegram
#' dend12 %>% untangle("step2") %>% tanglegram
#' dend12 %>% untangle_DendSer %>% tanglegram
#' # but the combination is quite awsome:
#' dend12 %>% untangle_DendSer %>% untangle("step2") %>% tanglegram
#' }
untangle_DendSer <- function(dend, ...) {
   dendlist(
      rotate_DendSer(dend[[1]]),
      rotate_DendSer(dend[[2]])
   )
}
