#!/usr/bin/env Rscript

################################################################################
# This file is part of polap.
#
# polap 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 3 of the License, or (at your option) any later 
# version.
#
# polap 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.
#
# You should have received a copy of the GNU General Public License along with 
# polap. If not, see <https://www.gnu.org/licenses/>.
################################################################################

suppressPackageStartupMessages(library("dplyr"))
suppressPackageStartupMessages(library("readr"))
suppressPackageStartupMessages(library("Biostrings"))
suppressPackageStartupMessages(library("chloroplot"))
args = commandArgs(trailingOnly=TRUE)

if (length(args) > 0) {
  input1 <- args[1]
  input2 <- args[2]
} else {
  s="bioprojects"
  input_dir0 <- paste0("/media/h2/goshng/figshare/", s, "/o/1")
  input1 <- paste0(input_dir0, "/60-chloroplot/annotation.bed")
  input2 <- paste0(input_dir0, "/mt.3.fa")
}

y1 <- read_tsv(input1, col_names = FALSE)
x1 <- readDNAStringSet(input2)

# library(dplyr)
# library(readr)
# library(Biostrings)
# library(chloroplot)

#' Generate table for PlotGenome function
#'
#' @param gbfile A character. It is the GI or GenBank accession for the
#' interested specie's chloroplast genome files.
#' @param local.file A logical value. If it is \code{TRUE}, the value passed to
#' \code{gbfile} should be a local GB file.
#' @param gc.window A integer. It indicates the window sized for plot
#' GC count.
#'
#' @return A list. It contains 3 tables:
#' \itemize{
#'   \item ir_table: a data frame contains information for IR region.
#'   \item gene_table: a data frame contains information of genes.
#'   \item gc_count: a data frame contains GC count information.
#' }
#'
#' @export
#' @importFrom magrittr %>%
#' @import dplyr
PlotTab2 <- function(gbfile, local.file = FALSE, gc.window = 100){
  my_env <- new.env(parent = emptyenv())
  my_env$gb <- NULL
  my_env$def <- NULL
  my_env$sp_name <- NULL
  my_env$genome <- NULL
  my_env$l <- NULL
  my_env$gene_table <- NULL
  my_env$ir <- NULL
  if (local.file){
    tryCatch({
      my_env$gb <- genbankr::readGenBank(gbfile)
      my_env$genome <- genbankr::getSeq(my_env$gb)[[1]]
      #genome <- rdnFixer(genome)
      my_env$l<- Biostrings::nchar(my_env$genome)
      my_env$def <- my_env$gb@definition
      my_env$sp_name <- sp.name(my_env$def)
      my_env$gene_table <- geneTableRead(my_env$gb, my_env$genome)
    }, error = function(e){
      my_env$gb <- genbankr::parseGenBank(gbfile)
      my_env$def <- my_env$gb$DEFINITION
      my_env$sp_name <- sp.name(my_env$def)
      my_env$genome <- my_env$gb$ORIGIN[[1]]
      my_env$l <- Biostrings::nchar(my_env$genome)
      my_env$gene_table <- geneTableParsed(my_env$gb, my_env$genome)
    })

  } else {
    tryCatch({
      my_env$gb <- genbankr::readGenBank(text = fetch.gb(gbfile))
      my_env$genome <- genbankr::getSeq(my_env$gb)
      my_env$l <- Biostrings::nchar(my_env$genome)
      my_env$def <- my_env$gb@definition
      my_env$sp_name <- sp.name(my_env$df)
      my_env$gene_table <- geneTableRead(my_env$gb, my_env$genome)
    }, error = function(e){
      my_env$gb <- genbankr::parseGenBank(text = fetch.gb(gbfile))
      my_env$def <- my_env$gb$DEFINITION
      my_env$sp_name <- sp.name(my_env$def)
      my_env$genome <- my_env$gb$ORIGIN[[1]]
      my_env$l <- Biostrings::nchar(my_env$genome)
      my_env$gene_table <- geneTableParsed(my_env$gb, my_env$genome)
    })
  }

  # 1. Organelle ------------------------------------------------------------

  plastid <- TRUE

  if (grepl("mitochondrion", my_env$def)){
    plastid <- FALSE
  }

  # 2. IR LSC SSC -----------------------------------------------------------
  # when seed.size is too short it will raise some error in irDetect function
  # If it is too long, it cannot correctly detect the IR resions has mutation
  # closing the ends.
  if (plastid){
    tryCatch({
      my_env$ir <- irDetect(my_env$genome, seed.size = 100)
    }, error = function(e){
      my_env$ir <- irDetect(my_env$genome, seed.size = 1000)
    }, warning = function(w) {
      my_env$ir <- irDetect(my_env$genome, seed.size = 1000)
    })
    gene_class <- c("psa","psb","pet","atp","ndh","rbc","rpo","rps","rpl",
                  "clp|mat|inf","ycf","trn","rrn")
  } else {
    my_env$ir <- list(ir_table = NULL, indel_table = NULL)
    gene_class <- c("nad|nd","sdh","cob","cox|cytb","atp","ccmF","mtt","rps","rpl",
                  "mat","orf","trn","rrn")
  }

  my_env$gene_table$class <- rep("OTHER", nrow(my_env$gene_table))

  for (i in gene_class){
    my_env$gene_table$class[which(grepl(as.character(i),
                                 my_env$gene_table$gene, perl = TRUE,
                                ignore.case = TRUE))] <- i
  }

  # 3. GC count -------------------------------------------------------------
  if (my_env$l > 500000){
    gc.window <- 200
  } else if (my_env$l < 100000){
    gc.window <- 50
  }
  gc_count_list <- gc_count(my_env$genome, view.width = gc.window)
  gc_count <- gc_count_list[[1]]
  gc_total <- gc_count_list[[2]]
  gc_count$chr <- rep("chr1", nrow(gc_count))
  gc_count <- select(gc_count, chr, position, gc_count)

  tables <- list(ir_table = my_env$ir$ir_table, indel_table = my_env$ir$indel_table,
                 gc_count = gc_count, gc_total = gc_total, plastid = plastid,
                 sp_name = my_env$sp_name, genome_len = my_env$l, gene_table = my_env$gene_table,
                 genome = my_env$genome)

  

  return(tables)
}

#' Generate Plasit Genome Plot
#'
#' @param plot.tables a list contains information of IR region, gene, and gc
#' count of the genome. It can be generated by function \code{\link{PlotTab}}.
#' @param save A logical value. If it is \code{TRUE}, the plot will be saved in
#' work directory.
#' @param file.type A charactor. It indicates the format of the file in which
#' the plot will be saved. Options are: "pdf", "png", "jpeg","bmp", "tiff".
#' By default, it is set as "pdf".
#' @param file.name A charactor. It indicates the name of the file in which
#' the plot will be saved. By default, it is set as the specie's name.
#' @param shadow A logical value. If it is \code{TRUE}, the section of IR
#' regions will be highlighted by shadows.
#' @param shadow.color An R color object. It indicates the color for the shadow
#' casted from IR sectors.
#' @param legend A logical value. If it is \code{TRUE}, the legend for gene
#' colors will be shown.
#' @param show.indel A logical value. If it is \code{TRUE}, the SNP, insertion
#' and deletion areas in IR regions will be highlighted on the plot.
#' @param ssc.converse A logical value. If it is \code{TRUE}, the SSC region
#' will be converted to its reverse complementary version
#' @param lsc.converse A logical value. If it is \code{TRUE}, the LSC region
#' will be converted to its reverse complementary version
#' @param ira.converse A logical value. If it is \code{TRUE}, the IRA region
#' will be converted to its reverse complementary version
#' @param irb.converse A logical value. If it is \code{TRUE}, the IRB region
#' will be converted to its reverse complementary version
#' @param background An R color object. It indicates the color for the background of
#' entire plot area.
#' @param height A vector of numeric value. The elements of it indicat the
#' height of gene layer, GC count layer and IR region layer, respectively.
#' Default setting is "0.1, 0.2, 0.07". The taltal circle plot region always
#' has a radius of 1, so a height of 0.1 means 10\% of the circle radius.
#' @param gc.color An R color object. It indicates the color for the lines in gc count
#' plot.
#' @param gc.background An R color object. It indicates the color for the background
#' of gc count plot area.
#' @param info.background An R color object. It indicates the color for the background
#' of central area where species' information was shown.
#' @param ir.color An R color object. It indicates the color for the background
#' of IR sectors.
#' @param ssc.color An R color object. It indicates the color for the background
#' of SSC sectors.
#' @param lsc.color An R color object. It indicates the color for the background
#' of LSC sectors.
#' @param ir.gc A logical value. If it is \code{TRUE}, the gc content for
#' IR, LSC, and SSC regions will be plot with deep colors.
#' @param gc.per.gene A logical value. If it is \code{TRUE}, the gc content for
#' each gene will be plot on the gene layer with deep colors.
#' @param pseudo A logical value. If it is \code{TRUE}, the pseudo genes (if
#' there is some in the species) will be marked with a "*" at the end of the
#' labels.
#' @param cu.bias A logical value. If it is \code{TRUE}, the condon usage bias
#' metric for each gene will be shown in the labels. The metric “Measure
#' Independent of Length and Composition (MILC)” was used for evaluate the bias.
#' You can find more details in the reference paper.
#' @param text.size A numeric value. It indicates the size of all texts in the
#' plot. For exmple, \code{text.size = 1.5} means all the texts in the plot will
#' be enlarged as 1.5 times of their original size.
#' @param gc.per.gene A logical value. If it is \code{TRUE}, the GC content of
#' each gene will be show by a darker part in gene rectangles.
#' @param genome.length A logical value. If it is \code{TRUE}, the length of
#' genome will be shown in the center of the plot.
#' @param total.gc A logical value. If it is \code{TRUE}, the GC content of
#' whole genome will be shown in the center of the plot.
#' @param gene.no A logical value. If it is \code{TRUE}, the number of genes in
#' the genome will be shown in the center of the plot.
#' @param rrn.no A logical value. If it is \code{TRUE}, the number of rRNAs in
#' the genome will be shown in the center of the plot.
#' @param trn.no A logical value. If it is \code{TRUE}, the number of tRNAs in
#' the genome will be shown in the center of the plot.
#' @param organelle A logical value. If it is \code{TRUE}, the organelle type of
#' the genome will be shown in the center of the plot.
#' @param psa.color An R color object. It indicates the color for genes of
#' photosystem I
#' @param psb.color An R color object. It indicates the color for genes of
#' photosystem II
#' @param pet.color An R color object. It indicates the color for genes of
#' cytochrome b/f complex
#' @param atp.color An R color object. It indicates the color for genes of
#' ATP synthesis
#' @param ndh.color An R color object. It indicates the color for genes of
#' NADH dehydrogenase
#' @param rbc.color An R color object. It indicates the color for genes of
#' RubisCO larg subunit
#' @param rpo.color An R color object. It indicates the color for genes of
#' RNA polymerase
#' @param rsp.color An R color object. It indicates the color for genes of
#' small ribosomal protein
#' @param rpl.color An R color object. It indicates the color for genes of
#' large ribosomal protein
#' @param clp_mat_inf.color An R color object. It indicates the color for genes
#' of clpP, matK, or infA
#' @param ycf.color An R color object. It indicates the color for genes of
#' hypothetical reading frame
#' @param trn.color An R color object. It indicates the color for genes of
#' transfer RNA
#' @param rrn.color An R color object. It indicates the color for genes of
#' ribosomal RNA
#' @param other_gene.color An R color object. It indicates the color for other
#' genes
#' @param show.gene A vector of characters. It indicates which classes of genes
#' will be shown on the plot. A valiable values are "psa","psb","pet","atp",
#' "ndh","rbc", "rpo","rps","rpl", "clp|mat|inf","ycf", "trn","rrn", "OTHER"
#' @param gene_axis_ir.color An R color object. It indicates the color for other
#' genes.
#' @param gene_axis_lsc.color An R color object. It indicates the color for other
#' genes.
#' @param gene_axis_ssc.color An R color object. It indicates the color for other
#' genes.
#' @param customize.ring1 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{position}: 1-base genomic coordinate for the features.
#'   \item \strong{value}: the values for the features.
#' }
#'
#' @param customize.ring1.type A charactor. It indicate the plot type in
#' customize.ring1. Avaliable values are "line", "line + filling", "line + dot",
#' "line + dot + filling", "step line", "step line + filling", "vertical line"
#' @param customize.ring1.color An R color object. It indicates the color for
#' the plots in customized ring 1.
#' @param customize.ring2 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{position}: 1-base genomic coordinate for the features.
#'   \item \strong{value}: the values for the features.
#' }
#' @param customize.ring2.type A charactor. It indicate the plot type in
#' customize.ring2. Avaliable values are "line", "line + filling", "line + dot",
#' "line + dot + filling", "step line", "step line + filling", "vertical line"
#' @param customize.ring2.color An R color object. It indicates the color for
#' the plots in customized ring 2.
#' @param customize.ring3 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{start}: 1-base genomic coordinate for the start point of the
#'   features.
#'   \item \strong{end}: 1-base genomic coordinate for the end point of the
#'   features.
#'   \item \strong{value}: the values for the features.
#' }
#' @param customize.ring3.color An R color object. It indicates the color for
#' the plots in customized ring 3.
#' @return  A plot for chloroplast genome.
#'
#' @references Supek, Fran, and Kristian Vlahovicek. “Comparison of codon usage
#' measures and their applicability in prediction of microbial gene
#' expressivity.” BMC bioinformatics vol. 6 182. 19 Jul.
#' 2005, doi:10.1186/1471-2105-6-182
#'
#' @importFrom magrittr %>%
#' @import dplyr
#' @export
PlotPlastidGenome2 <- function(plot.tables, save = TRUE, file.type = "pdf",
                       text.size = 1, height = c(0.1, 0.2, 0.07),
                       file.name = NULL, shadow = TRUE, ir.gc = TRUE,
                       gc.per.gene = TRUE, pseudo = TRUE, legend = TRUE,
                       ssc.converse = FALSE, lsc.converse = FALSE,
                       ira.converse = FALSE, irb.converse = FALSE,
                       genome.length = TRUE, total.gc = TRUE, show.indel = TRUE,
                       gene.no = TRUE, rrn.no = TRUE,trn.no = TRUE,
                       organelle_type = TRUE,
                       background = "grey90",gc.color = "grey30",
                       gc.background = "grey70", info.background = "black",
                       ir.color = "#2F3941", ssc.color = "#82B6E2",
                       lsc.color = "#299E96", shadow.color = "#0000FF20",
                       psa.color = "#2A6332", psb.color = "#4C8805",
                       pet.color = "#7F992C", atp.color = "#9FBB3D",
                       ndh.color = "#FEEE50", rbc.color = "#4D9E3F",
                       rpo.color = "#AE2D29", rsp.color = "#D6AD7C",
                       rpl.color = "#9C7A4B", clp_mat_inf.color = "#D9662D",
                       ycf.color = "#71B8A9", trn.color = "#172C7F",
                       rrn.color = "#D1382A", other_gene.color = "#7D7D7D",
                       show.genes = c("psa","psb","pet","atp","ndh","rbc",
                                      "rpo","rps","rpl", "clp|mat|inf","ycf",
                                      "trn","rrn", "OTHER"),
                       gene_axis_ir.color = ir.color,
                       gene_axis_ssc.color = ssc.color,
                       gene_axis_lsc.color = lsc.color,
                       cu.bias = TRUE, customize.ring1 = NULL,
                       customize.ring1.type = "line",
                       customize.ring1.color = gc.color,
                       customize.ring2 = NULL,
                       customize.ring2.type = "line",
                       customize.ring2.color = gc.color,
                       customize.ring3 = NULL,
                       customize.ring3.color = gc.color){

  # Unpack plot.table
  genome <- plot.tables$genome
  ir_table <- plot.tables$ir_table
  gc_count <- plot.tables$gc_count
  gc_total <- plot.tables$gc_total
  sp_name <- plot.tables$sp_name
  gene_table <- plot.tables$gene_table
  genome <- plot.tables$genome
  indel_table <- plot.tables$indel_table

  l <- Biostrings::nchar(genome)

  # 1. Modify gene table

  # ssc covert
  if (ssc.converse){
    if (nrow(ir_table) == 1){
      warning("Didn't get IR region from thid species. ",
              "It's impossible to convert SSC region.")
    } else{
      tmp <- convert_region(ir_table = ir_table, l = l, region = "SSC",
                            genome = genome, gene_table = gene_table,
                            customize.ring1 = customize.ring1,
                            customize.ring2 = customize.ring2,
                            customize.ring3 = customize.ring3)
      gene_table <- tmp$gene_table
      gc_count <- tmp$gc_count
      gc_total <- tmp$gc_total
      customize.ring1 <- tmp$customize.ring1
      customize.ring2 <- tmp$customize.ring2
      customize.ring3 <- tmp$customize.ring3
    }
  }

  # LSC covert
  if (lsc.converse){
    if (nrow(ir_table) == 1){
      warning("Didn't get IR region from thid species. ",
              "It's impossible to convert LSC region.")
      gene_table <- gene_table
    } else{
      tmp <- convert_region(ir_table = ir_table, l = l, region = "LSC",
                            genome = genome, gene_table = gene_table,
                            customize.ring1 = customize.ring1,
                            customize.ring2 = customize.ring2,
                            customize.ring3 = customize.ring3)
      gene_table <- tmp$gene_table
      gc_count <- tmp$gc_count
      gc_total <- tmp$gc_total
      customize.ring1 <- tmp$customize.ring1
      customize.ring2 <- tmp$customize.ring2
      customize.ring3 <- tmp$customize.ring3
    }
  }

  # IRA covert
  if (ira.converse){
    if (nrow(ir_table) == 1){
      warning("Didn't get IR region from thid species. ",
              "It's impossible to convert IRA region.")
    } else{
      tmp <- convert_region(ir_table = ir_table, l = l, region = "IRA",
                            genome = genome, gene_table = gene_table,
                            customize.ring1 = customize.ring1,
                            customize.ring2 = customize.ring2,
                            customize.ring3 = customize.ring3,
                            indel_table = indel_table)
      gene_table <- tmp$gene_table
      gc_count <- tmp$gc_count
      gc_total <- tmp$gc_total
      customize.ring1 <- tmp$customize.ring1
      customize.ring2 <- tmp$customize.ring2
      customize.ring3 <- tmp$customize.ring3
      indel_table <- tmp$indel_table
    }
  }

  # IRB covert
  if (irb.converse){
    if (nrow(ir_table) == 1){
      warning("Didn't get IR region from thid species. ",
              "It's impossible to convert IRB region.")
      gene_table <- gene_table
    } else{
      tmp <- convert_region(ir_table = ir_table, l = l, region = "IRB",
                            genome = genome, gene_table = gene_table,
                            customize.ring1 = customize.ring1,
                            customize.ring2 = customize.ring2,
                            customize.ring3 = customize.ring3,
                            indel_table = indel_table)
      gene_table <- tmp$gene_table
      gc_count <- tmp$gc_count
      gc_total <- tmp$gc_total
      customize.ring1 <- tmp$customize.ring1
      customize.ring2 <- tmp$customize.ring2
      customize.ring3 <- tmp$customize.ring3
      indel_table <- tmp$indel_table
    }
  }

  # colouring
  color_table <- plastidGeneColor(psa.color = psa.color, psb.color = psb.color,
                           pet.color = pet.color, atp.color = atp.color,
                           ndh.color = ndh.color, rbc.color = rbc.color,
                           rpo.color = rpo.color, rsp.color = rsp.color,
                           rpl.color = rpl.color, clp_mat_inf.color = clp_mat_inf.color,
                           ycf.color = ycf.color, trn.color = trn.color,
                           rrn.color = rrn.color, other_gene.color = other_gene.color)

  gene_table <- dplyr::left_join(gene_table, color_table, by = c("class" = "acronym"))

  gene_table <- gene_table[which(gene_table$class %in% show.genes), ]
  gene_table$gene <- gsub('(.{1,20})(\\s)', '\\1\n', gene_table$gene)
  color_table <- color_table[which(color_table$acronym %in% unique(gene_table$class)), ]

  # gene labels
  gene_table$gene_label <- gene_table$gene
  if (cu.bias){
    gene_table$gene_label <- apply(gene_table[, c("gene_label", "cu_bias")], 1,
                          function(x){
                            if (is.na(x[2])){
                              return(x[1])
                            } else {
                              return(paste0(x[1], " (",
                                            signif(as.numeric(x[2]), 2), ")"))
                            }
                          })
  }

  if (pseudo){
    gene_table$gene_label <- apply(gene_table[, c("gene_label", "pseudo")], 1,
                                   function(x){
                                     if (x[2]){
                                       return(paste0(x[1], " *"))
                                     } else {
                                       return(x[1])
                                     }
                                   })
  }
  genome <- genome
  gene_table_r <- filter(gene_table, strand == "-") %>%
    select(chr, start, end, gene, col, gc_count, gene_label) %>%
    arrange(start)
  gene_table_f <- filter(gene_table, strand == "+") %>%
    select(chr, start, end, gene, col, gc_count, gene_label) %>%
    arrange(start)

  # 2. Set colors
  ir_table$bg_col <- rep(NA, nrow(ir_table))
  ir_table$bg_col[ir_table$name == "LSC"] <- lsc.color
  ir_table$bg_col[ir_table$name == "SSC"] <- ssc.color
  ir_table$bg_col[grepl("IR", ir_table$name)] <- ir.color
  ir_table$bg_col[ir_table$name == "Genome"] <- lsc.color


  ir_table$axis_col <- rep(NA, nrow(ir_table))
  ir_table$axis_col[ir_table$name == "LSC"] <- gene_axis_lsc.color
  ir_table$axis_col[ir_table$name == "SSC"] <- gene_axis_ssc.color
  ir_table$axis_col[grepl("IR", ir_table$name)] <- gene_axis_ir.color
  ir_table$axis_col[ir_table$name == "Genome"] <- gene_axis_lsc.color

  # Automatically adjust colors
  info.color <- CompColor(info.background)

  ir_table$inf_col <- rep(NA, nrow(ir_table))
  ir_table$inf_col[ir_table$name=="LSC"] <- CompColor(lsc.color)
  ir_table$inf_col[ir_table$name=="SSC"] <- CompColor(ssc.color)
  ir_table$inf_col[grepl("IR", ir_table$name)] <- CompColor(ir.color)
  ir_table$inf_col[ir_table$name == "Genome"] <- CompColor(lsc.color)

  if (!is.null(indel_table)){
    indel_table$bg_color <- rep("White", #Transparent("#FFFFFF", 0.9),
                                            nrow(indel_table))
  }


  ir_table$y <- rep(0.25, nrow(ir_table))
  ir_table$y[grepl("IR", ir_table$name)] <- 0.75

  # 3. Genome information
  n_trn <- sum(grepl("trn", gene_table$gene, perl = TRUE))
  n_rrn <- sum(grepl("rrn", gene_table$gene, perl = TRUE))
  n_gene <- nrow(gene_table) - n_trn - n_rrn

  # 4. Generate plot
  # Initialize the plot device
  if (save){
    if (is.null(file.name)){
      file <- sp_name
    } else {
      file <- file.name
    }
    if (!file.type %in% c("jpeg", "bmp", "png", "tiff", "pdf")){
      warning("Can not save plot in ", file.type, " format. Avaliable formats
                are 'jpeg', 'bmp', 'png', 'tiff',and 'pdf'.")
    } else if (file.type  == "pdf") {
      grDevices::pdf(paste(file, file.type, sep="."), width=10.3, height=8.9)
    } else {
      do.call(file.type, args=list(filename=paste(file, file.type, sep="."),
                                   width = 10.3, height = 8.9, units = "in",
                                   res = 1000))
    }
  }


  # Initialize the layout
  ssc_deg<-ir_table$center[which(ir_table$name=="SSC")][1]
  if ((length(ssc_deg) == 1) & !is.na(ssc_deg)){
    ssc_deg <- 360 - round(((ssc_deg)/l) * 360)
    rotate <- 270 - ssc_deg
  } else {
    rotate <- -90
  }

  # Track indexes
  track_index <- 1:8
  names(track_index) <- c("gene out 1", "gene out 2", "gene", "gene inner 1",
                          "gene inner 2", "arrow", "gc count", "ir region")

  if (!is.null(customize.ring1)){
    track_index[c("arrow", "gc count", "ir region")] <- track_index[c("arrow", "gc count", "ir region")] + 1
    track_index["customize 1"] <- track_index["gene inner 2"] + 1
  }

  if (!is.null(customize.ring2)){
    track_index[c("arrow", "gc count", "ir region")] <- track_index[c("arrow", "gc count", "ir region")] + 1
    track_index["customize 2"] <- track_index["arrow"] - 1
  }

  if (!is.null(customize.ring3)){
    track_index[c("arrow", "gc count", "ir region")] <- track_index[c("arrow", "gc count", "ir region")] + 1
    track_index["customize 3"] <- track_index["arrow"] - 1
  }

  # Track heights
  n_customize_ring <- sum(c(!is.null(customize.ring1), !is.null(customize.ring2), !is.null(customize.ring3)))
  if (n_customize_ring == 1){
    height[2] <- height[2]/1.5
  } else if (n_customize_ring == 2) {
    height[2] <- height[2]/2
    height[3] <- height[3] * 0.7
  } else if (n_customize_ring == 3) {
    height[2] <- height[2]/2
    height[3] <- height[3] * 0.7
    height[1] <- height[1] *0.7
  }

  circlize::circos.clear()
  circlize::circos.par(start.degree = rotate,
                       gap.after = 0,
                       track.margin = c(0, 0), cell.padding = c(0, 0, 0, 0))
  circlize::circos.genomicInitialize(data=data.frame(chr="chr1", start=0, end=l,
                                                     stringsAsFactors = FALSE),
                                     plotType = NULL)

  # 1.2. gene label outside
  if (nrow(gene_table_r) == 0 ) {
    # Background
    circlize::draw.sector(0, 360,
                          rou1 = 1,
                          rou2 = 0,
                          col = background, border = NA)
  } else {
    circlize::circos.genomicLabels(gene_table_r, labels = gene_table_r$gene_label,
                                   side = "outside",cex = 0.5 * text.size,
                                   connection_height = circlize::convert_height(3, "mm"),
                                   labels_height = max(graphics::strwidth(gene_table_r$gene_label,
                                                                          cex = 0.5 * text.size,
                                                                          font = graphics::par("font")))
    )
    # Background
    circlize::draw.sector(0, 360,
                          rou1 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                              track.index = 2),
                          rou2 = 0,
                          col = background, border = NA)
  }



  # 3. Gene rectangles
  if (nrow(gene_table_r) != 0 & nrow(gene_table_f) != 0) {
    circlize::circos.genomicTrack(gene_table_f, factors = as.factor("chr1"),
                                  ylim = c(-1, 1), bg.border = NA,
                                  track.height = height[1], #circlize::convert_height(10, "mm"),
                                  panel.fun = function(region, value, ...) {

                                    if(gc.per.gene){
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = - gene_table_f$gc_count,
                                        ytop = 0,
                                        col = gene_table_f$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_f$col, 0.7),
                                        border = NA
                                      )

                                      # genes lay on reverse chain
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = gene_table_r$gc_count,
                                        col = gene_table_r$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_r$col, 0.7),
                                        border = NA
                                      )
                                    } else {
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = gene_table_f$col
                                      )

                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = gene_table_r$col
                                      )
                                    }

                                    # the bars in the middle indicate the IR, SSR, LSR
                                    circlize::circos.rect(xleft = ir_table$start,
                                                          ybottom = - 0.05,
                                                          xright = ir_table$end,
                                                          ytop = 0.05,
                                                          col = ir_table$axis_col,
                                                          border = NA)
                                  })
  } else if (nrow(gene_table_f) != 0){
  circlize::circos.genomicTrack(gene_table_f, factors = as.factor("chr1"),
                                 ylim = c(-1, 1), bg.border = NA,
                                 track.height = height[1], #circlize::convert_height(10, "mm"),
                                 panel.fun = function(region, value, ...) {

                                   if (gc.per.gene){
                                     # genes lay on forward chain
                                     circlize::circos.genomicRect(
                                       gene_table_f[, c("start", "end")],
                                       value = gene_table_f$gene,
                                       ybottom = - gene_table_f$gc_count,
                                       ytop = 0,
                                       col = gene_table_f$col,
                                       border = NA)
                                     circlize::circos.genomicRect(
                                       gene_table_f[, c("start", "end")],
                                       value = gene_table_f$gene,
                                       ybottom = -1,
                                       ytop = 0,
                                       lwd = 0.5,
                                       col = Transparent(gene_table_f$col, 0.7),
                                       border = NA
                                     )
                                   } else {
                                     # genes lay on forward chain
                                     circlize::circos.genomicRect(
                                       gene_table_f[, c("start", "end")],
                                       value = gene_table_f$gene,
                                       ybottom = -1,
                                       ytop = 0,
                                       lwd = 0.5,
                                       col = gene_table_f$col
                                     )
                                   }
                                   # the bars in the middle indicate the IR, SSR, LSR
                                   circlize::circos.rect(xleft = ir_table$start,
                                                         ybottom = - 0.05,
                                                         xright = ir_table$end,
                                                         ytop = 0.05,
                                                         col = ir_table$axis_col,
                                                         border = NA)
                                 })
    track_index[3:length(track_index)] <- track_index[3:length(track_index)] - 2
    track_index <- track_index[-which(names(track_index) %in% c("gene out 1", "gene out 2"))]
  } else if (nrow(gene_table_r) != 0) {
    circlize::circos.genomicTrack(gene_table_r, factors = as.factor("chr1"),
                                  ylim = c(-1, 1), bg.border = NA,
                                  track.height = height[1], #circlize::convert_height(10, "mm"),
                                  panel.fun = function(region, value, ...) {

                                    if(gc.per.gene){
                                      # genes lay on reverse chain
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = gene_table_r$gc_count,
                                        col = gene_table_r$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_r$col, 0.7),
                                        border = NA
                                      )
                                    } else {
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = gene_table_r$col
                                      )
                                    }

                                    # the bars in the middle indicate the IR, SSR, LSR
                                    circlize::circos.rect(xleft = ir_table$start,
                                                          ybottom = - 0.05,
                                                          xright = ir_table$end,
                                                          ytop = 0.05,
                                                          col = ir_table$axis_col,
                                                          border = NA)
                                  })
    track_index[(which(names(track_index) == "gene inner 2") + 1):length(track_index)] <-
      track_index[(which(names(track_index) == "gene inner 2") + 1):length(track_index)] - 2
    track_index <- track_index[-which(names(track_index) %in% c("gene inner 1", "gene inner 2"))]
  } else {
    track_index <- track_index[6:length(track_index)] -5
  }

  # 4.5. gene labels inside
  if (nrow(gene_table_f) != 0){
    circlize::circos.genomicLabels(gene_table_f, labels = gene_table_f$gene_label,
                                   side = "inside", cex = 0.5 * text.size,
                                   connection_height = circlize::convert_height(3, "mm"),
                                   labels_height = max(graphics::strwidth(gene_table_f$gene_label,
                                                                          cex = 0.5 * text.size,
                                                                          font = graphics::par("font"))))
  }

  # customized ring 1
  if (!is.null(customize.ring1)) {
    customize.ring1 <- customize.ring1[order(customize.ring1$position), ]
    customize.ring1$chr <- rep("chr1", nrow(customize.ring1))
    ylim <- c(min(customize.ring1$value), max(customize.ring1$value))
    bar_color <- ifelse(customize.ring1$value > 0, "orangered3", "steelblue")
    if (min(customize.ring1$value) > 0) {
      ylim[1] <- 0
      bar_color <- rep(customize.ring1.color, nrow(customize.ring1))
    }
    if (max(customize.ring1$value) < 0){
      ylim[2] <- 0
      bar_color <- rep(customize.ring1.color, nrow(customize.ring1))
    }
    style <- switch(customize.ring1.type,
           "line" = list(type = "l", arear = FALSE, col = customize.ring1.color, lwd = 0.5),
           "line + filling" = list(type = "l", arear = TRUE, col = customize.ring1.color, lwd = 0.01),
           "line + dot" = list(type = "o", arear = FALSE, col = bar_color, lwd = 0.5),
           "line + dot + filling" = list(type = "o", arear = TRUE, col = bar_color, lwd = 0.01),
           "step line" = list(type = "s", arear = FALSE, col = customize.ring1.color, lwd = 0.5),
           "step line + filling" = list(type = "s", arear = TRUE, col = customize.ring1.color, lwd = 0.01),
           "vertical line" = list(type = "h", arear = FALSE, col = bar_color, lwd = 0.5))

    circlize::circos.track(factors =as.factor(customize.ring1$chr),
                           x = customize.ring1$position,
                           y = customize.ring1$value, ylim = ylim,
                           track.height = height[2]/2,
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             circlize::circos.lines(x, y, type = style$type,
                                                    area = style$area,
                                                    baseline = 0,
                                                    pch = 1,
                                                    cex = 0.2 * text.size,
                                                    col = style$col,
                                                    lwd = style$lwd)
                             circlize::circos.segments(x0=0, x1=l, y0=0,
                                                       y1=0, lwd=0.5,
                                                       lty="16",
                                                       col=darken(customize.ring1.color, 0.7))
                           })

  }

  # customized ring 2
  if (!is.null(customize.ring2)) {
    customize.ring2 <- customize.ring2[order(customize.ring2$position), ]
    customize.ring2$chr <- rep("chr1", nrow(customize.ring2))
    ylim <- c(min(customize.ring2$value), max(customize.ring2$value))
    bar_color <- ifelse(customize.ring2$value > 0, "orangered3", "steelblue")
    if (min(customize.ring2$value) > 0) {
      ylim[1] <- 0
      bar_color <- rep(customize.ring2.color, nrow(customize.ring2))
    }
    if (max(customize.ring2$value) < 0){
      ylim[2] <- 0
      bar_color <- rep(customize.ring2.color, nrow(customize.ring2))
    }
    style <- switch(customize.ring2.type,
                    "line" = list(type = "l", arear = FALSE, col = customize.ring2.color, lwd = 0.5),
                    "line + filling" = list(type = "l", arear = TRUE, col = customize.ring2.color, lwd = 0.01),
                    "line + dot" = list(type = "o", arear = FALSE, col = bar_color, lwd = 0.5),
                    "line + dot + filling" = list(type = "o", arear = TRUE, col = bar_color, lwd = 0.01),
                    "step line" = list(type = "s", arear = FALSE, col = customize.ring2.color, lwd = 0.5),
                    "step line + filling" = list(type = "s", arear = TRUE, col = customize.ring2.color, lwd = 0.01),
                    "vertical line" = list(type = "h", arear = FALSE, col = bar_color, lwd = 0.5))

    circlize::circos.track(factors =as.factor(customize.ring2$chr),
                           x = customize.ring2$position,
                           y = customize.ring2$value, ylim = ylim,
                           track.height = height[2]/2,
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             circlize::circos.lines(x, y, type = style$type,
                                                    area = style$area,
                                                    baseline = 0,
                                                    pch = 1,
                                                    cex = 0.2 * text.size,
                                                    col = style$col,
                                                    lwd = style$lwd)
                             circlize::circos.segments(x0=0, x1=l, y0=0,
                                                       y1=0, lwd=0.5,
                                                       lty="16",
                                                       col=darken(customize.ring2.color, 0.7))
                           })

  }

  # customize.ring 3
  if (!is.null(customize.ring3)) {
    customize.ring3$chr <- rep("chr1", nrow(customize.ring3))
    ylim <- c(min(customize.ring3$value), max(customize.ring3$value))
    if (min(customize.ring3$value) > 0) {
      ylim[1] <- 0
    }
    if (max(customize.ring3$value) < 0){
      ylim[2] <- 0
    }
    circlize::circos.track(factors =as.factor(customize.ring3$chr),
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           track.height = height[2]/2,
                           ylim = ylim,
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             if (min(customize.ring3$value) < 0 &
                                 max(customize.ring3$value) > 0) {
                               df_large <- customize.ring3[which(customize.ring3$value > 0), ]
                               df_less <- customize.ring3[which(customize.ring3$value < 0), ]
                               circlize::circos.rect(xleft = df_large$start,
                                                     xright = df_large$end,
                                                     ybottom = 0,
                                                     ytop = df_large$value,
                                                     col = "orangered3",
                                                     border = NA)
                               circlize::circos.rect(xleft = df_less$start,
                                                     xright = df_less$end,
                                                     ybottom = df_less$value,
                                                     ytop = 0,
                                                     col = "steelblue",
                                                     border = NA)
                             } else if (min(customize.ring3$value) < 0) {
                               circlize::circos.rect(xleft = customize.ring3$start,
                                           xright = customize.ring3$end,
                                           ybottom = customize.ring3$value,
                                           ytop = 0,
                                           col = customize.ring3.color,
                                           border = NA)
                             } else {
                               circlize::circos.rect(xleft = customize.ring3$start,
                                                    xright = customize.ring3$end,
                                                    ybottom = 0,
                                                    ytop = customize.ring3$value,
                                                    col = customize.ring3.color,
                                                    border = NA)
                            }
                           })
  }
  # 6. Arrow outside gnome axis
  circlize::circos.track(ylim = c(0, 1), track.height = 0.06, bg.border = NA,
                         track.margin = c(0, circlize::convert_height(1, "mm")),
                         panel.fun = function(x, y) {
                           circlize::circos.arrow(x1 = l - l %/% 40,
                                                  x2 = l,
                                                  y = 0.85,
                                                  arrow.position="start",
                                                  col = MildColor(background),
                                                  border = NA,
                                                  arrow.head.length = circlize::convert_x(3, "mm"),
                                                  width = 0.15)
                           # circlize::circos.genomicAxis(h = "bottom")
                         })



  # 7. GC content
  circlize::circos.track(factors =as.factor(gc_count$chr),
                         x=gc_count$position,
                         y = 1- gc_count$gc_count,
                         ylim = c(0, 1),
                         track.height = height[2],
                         bg.border = NA, bg.col = gc.background,
                         panel.fun = function(x, y) {
                           circlize::circos.lines(x, y, type = "s", area = TRUE,
                                                  baseline = "top",
                                                  col = gc.color, lwd = 0.00001)
                           circlize::circos.arrow(x1= 0,
                                                  x2= l %/% 35,
                                                  y= 0.9,
                                                  col=MildColor(gc.color),
                                                  border=NA,
                                                  arrow.head.length=circlize::convert_x(3, "mm"),
                                                  width=0.15 * 0.05 / height[2])
                           circlize::circos.segments(x0=0, x1=l, y0=0.25,
                                                     y1=0.25, lwd=0.5,
                                                     lty="16", col=MildColor(gc.background))
                           circlize::circos.segments(x0=0, x1=l, y0=0.5,
                                                     y1=0.5, lwd=0.6,
                                                     lty="11", col=MildColor(gc.background))
                           circlize::circos.segments(x0=0, x1=l, y0=0.75,
                                                     y1=0.75, lwd=0.5,
                                                     lty="16", col=MildColor(gc.color))
                           circlize::circos.genomicAxis(h = "top", labels.cex = 0.4 * text.size)
                         })
  #circos.yaxis(at=c(0.25,0.5,0.75),labels.cex=0.25 * text.size,lwd=0,tick.length=0,
  #             labels.col="grey40",col="#FFFFFF")

  # 8. inner ring for IR, SSR, LSR
  circlize::circos.genomicTrack(ir_table, bg.border = NA,
                                ylim = c(0, 1),track.height = height[3],
                                panel.fun = function(region, value, ...) {
                                  if (ir.gc){
                                    circlize::circos.rect(xleft = ir_table$start,
                                                          ybottom = 0,#circlize::convert_y(0, "mm"),
                                                          xright = ir_table$end,
                                                          ytop = 1,#circlize::convert_y(3, "mm"),
                                                          col = Transparent(ir_table$bg_col, 0.7),
                                                          border = NA)
                                    circlize::circos.rect(xleft = ir_table$start,
                                                          ybottom =0,#circlize::convert_y(0, "mm"),
                                                          xright = ir_table$end,
                                                          ytop =  ir_table$gc_count,#circlize::convert_y(3, "mm"),
                                                          col = ir_table$bg_col,
                                                          border = NA)
                                  } else {
                                    circlize::circos.rect(xleft = ir_table$start,
                                                          ybottom = 0,#circlize::convert_y(0, "mm"),
                                                          xright = ir_table$end,
                                                          ytop = 1,#circlize::convert_y(3, "mm"),
                                                          col = ir_table$bg_col,
                                                          border = NA)
                                  }
                                  if (!is.null(indel_table) & show.indel){
                                    circlize::circos.rect(xleft = indel_table$position - 10,
                                                          ybottom = 0,#circlize::convert_y(0, "mm"),
                                                          xright = indel_table$position + 10,
                                                          ytop = 1,#circlize::convert_y(3, "mm"),
                                                          col = indel_table$bg_col,
                                                          border = NA)
                                    circlize::circos.points(x = indel_table$position,
                                                            y = 0.05,
                                                            col = indel_table$col,
                                                            pch = 19,
                                                            cex = 0.5 * text.size)
                                    # circlize::circos.text(x = indel_table$position,
                                    #                         y = 0.5,
                                    #                         col = indel_table$col,
                                    #                         labels = indel_table$string,
                                    #                         cex = 0.2 * text.size)
                                  }

                                  circlize::circos.text(x = ir_table$center,
                                                        y = ir_table$y, cex = 0.7 * text.size,
                                                        labels = ir_table$text,
                                                        facing = "bending.inside",
                                                        col = ir_table$inf_col,
                                                        niceFacing = TRUE)
                                })

  # Specie's information inthe central
  circlize::draw.sector(0, 360,
                        rou1 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                            track.index = track_index['ir region']),
                        rou2 = 0,
                        col = info.background, border = NA)

  if (organelle_type){
    graphics::text(0,0.10, sp_name, font=4, cex = 0.8 * text.size, col = info.color)
    graphics::text(0,0.05, "Plastid Genome", font=4, cex = 0.8 * text.size, col = info.color)
  } else{
    graphics::text(0,0.05, sp_name, font=4, cex = 0.8 * text.size, col = info.color)
  }

  ns <- c(paste(n_gene, "genes"), paste(n_rrn, "rRNAs"), paste(n_trn, "tRNAs"))[which(c(gene.no, rrn.no, trn.no))]
  text <- c(paste(ns, collapse = "; "), paste(prettyNum(l, big.mark = ","), "bp", " "),
            paste("GC:",round(gc_total, 2)*100,"%"))
  j <- 1
  if (cu.bias){
    cex = 0.7 * text.size
  } else {
    cex = 0.8 * text.size
  }
  for (i in which(c((length(ns) != 0), genome.length, total.gc))) {
    graphics::text(0,0.05 - 0.05 * j, text[i],
                   font=4, cex = cex, col = info.color)
    j <-  j + 1
  }

  # Highlight IR


  if (shadow & (nrow(ir_table) >= 4)){

    pos_s=circlize::circlize(ir_table$start[which(grepl("IR",
                                                                    ir_table$name))],
                             1, sector.index = "chr1", track.index = 1)
    pos_e=circlize::circlize(ir_table$end[which(grepl("IR",
                                                                  ir_table$name))],
                             1, sector.index = "chr1", track.index = 1)
    for (i in 1:nrow(pos_s)) {
      if ('gene' %in% names(track_index)){
        circlize::draw.sector(pos_s[i, "theta"], pos_e[i, "theta"],
                              #start.degree = 0, end.degree = 360 - 10,
                              rou1 = circlize::get.cell.meta.data("cell.top.radius",
                                                                  track.index = track_index['gene']),
                              rou2 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                                  track.index = track_index['gc count']),
                              col = shadow.color, border = NA)
      } else {
        circlize::draw.sector(pos_s[i, "theta"], pos_e[i, "theta"],
                              #start.degree = 0, end.degree = 360 - 10,
                              rou1 = circlize::get.cell.meta.data("cell.top.radius",
                                                                  track.index = track_index['arrow']),
                              rou2 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                                  track.index = track_index['gc count']),
                              col = shadow.color, border = NA)
      }

    }
    if (!is.null(indel_table) & show.indel) {
      pos_s=circlize::circlize(indel_table$position - 10,
                               1, sector.index = "chr1", track.index = 1)
      pos_e=circlize::circlize(indel_table$position + 10,
                               1, sector.index = "chr1", track.index = 1)
      for (i in 1:nrow(pos_s)) {
        if ('gene' %in% names(track_index)){
          circlize::draw.sector(pos_s[i, "theta"], pos_e[i, "theta"],
                                #start.degree = 0, end.degree = 360 - 10,
                                rou1 = circlize::get.cell.meta.data("cell.top.radius",
                                                                    track.index =  track_index['gene']),
                                rou2 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                                    track.index = track_index['gc count']),
                                col = Transparent("#FFFFFF", 0.5),
                                border = NA)
        } else {
          circlize::draw.sector(pos_s[i, "theta"], pos_e[i, "theta"],
                                #start.degree = 0, end.degree = 360 - 10,
                                rou1 = circlize::get.cell.meta.data("cell.top.radius",
                                                                    track.index =  track_index['arrow']),
                                rou2 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                                    track.index = track_index['gc count']),
                                col = Transparent("#FFFFFF", 0.9),
                                border = NA)
        }
      }
    }
  }
  # Add legend
  if (legend){
    legend(x = -1.27, y = -0.6, legend = color_table$label, cex = 0.6 * text.size,
           fill = color_table$col, box.col = "white")
  }

  if (save){
    grDevices::dev.off()
  }

}

#' Generate Mitochondrion Genome Plot
#'
#' @param plot.tables a list contains information of IR region, gene, and gc
#' count of the genome. It can be generated by function \code{\link{PlotTab}}.
#' @param save A logical value. If it is \code{TRUE}, the plot will be saved in
#' work directory.
#' @param file.type A charactor. It indicates the format of the file in which
#' the plot will be saved. Options are: "pdf", "png", "jpeg","bmp", "tiff".
#' By default, it is set as "pdf".
#' @param file.name A charactor. It indicates the name of the file in which
#' the plot will be saved. By default, it is set as the specie's name.
#' @param legend A logical value. If it is \code{TRUE}, the legend for gene
#' colors will be shown.
#' @param background An R color object. It indicates the color for the background of
#' entire plot area.
#' @param height A vector of numeric value. The elements of it indicat the
#' height of gene layer, GC count layer and IR region layer, respectively.
#' Default setting is "0.1, 0.2, 0.07". The taltal circle plot region always
#' has a radius of 1, so a height of 0.1 means 10\% of the circle radius.
#' @param gc.color An R color object. It indicates the color for the lines in gc count
#' plot.
#' @param gc.background An R color object. It indicates the color for the background
#' of gc count plot area.
#' @param info.background An R color object. It indicates the color for the background
#' of central area where species' information was shown.
#' @param gc.per.gene A logical value. If it is \code{TRUE}, the gc content for
#' each gene will be plot on the gene layer with deep colors.
#' @param pseudo A logical value. If it is \code{TRUE}, the pseudo genes (if
#' there is some in the species) will be marked with a "*" at the end of the
#' labels.
#' @param cu.bias A logical value. If it is \code{TRUE}, the condon usage bias
#' metric for each gene will be shown in the labels. The metric “Measure
#' Independent of Length and Composition (MILC)” was used for evaluate the bias.
#' You can find more details in the reference paper.
#' @param text.size A numeric value. It indicates the size of all texts in the
#' plot. For exmple, \code{text.size = 1.5} means all the texts in the plot will
#' be enlarged as 1.5 times of their original size.
#' @param gc.per.gene A logical value. If it is \code{TRUE}, the GC content of
#' each gene will be show by a darker part in gene rectangles.
#' @param genome.length A logical value. If it is \code{TRUE}, the length of
#' genome will be shown in the center of the plot.
#' @param total.gc A logical value. If it is \code{TRUE}, the GC content of
#' whole genome will be shown in the center of the plot.
#' @param gene.no A logical value. If it is \code{TRUE}, the number of genes in
#' the genome will be shown in the center of the plot.
#' @param rrn.no A logical value. If it is \code{TRUE}, the number of rRNAs in
#' the genome will be shown in the center of the plot.
#' @param trn.no A logical value. If it is \code{TRUE}, the number of tRNAs in
#' the genome will be shown in the center of the plot.
#' @param organelle A logical value. If it is \code{TRUE}, the organelle type of
#' the genome will be shown in the center of the plot.
#' @param nad.color An R color string. It indicates the color for genes of
#' complex I (NADH dehydrogenase)
#' @param sdh.color An R color string. It indicates the color for genes of
#' complex II (succinate dehydrogenase)
#' @param cob.color An R color string. It indicates the color for genes of
#' complex III (ubichinol cytochrome reductase)
#' @param cox.color An R color string. It indicates the color for genes of
#' complex IV (cytochrome c oxidase)
#' @param atp.color An R color string. It indicates the color for genes of
#' ATP synthase
#' @param ccmF.color An R color string. It indicates the color for genes of
#' cytochrome c biogenesi
#' @param mmt.color An R color string. It indicates the color for genes of
#' transport membrane protein
#' @param rps.color An R color string. It indicates the color for genes of
#' ribosomal proteins (SSU)
#' @param rpl.color An R color string. It indicates the color for genes of
#' ribosomal proteins (LSU)
#' @param mat.color An R color string. It indicates the color for genes of
#' maturases
#' @param orf.color An R color string. It indicates the color for ORFs
#' @param trn.color An R color object. It indicates the color for genes of
#' transfer RNA
#' @param rrn.color An R color object. It indicates the color for genes of
#' ribosomal RNA
#' @param other_gene.color An R color object. It indicates the color for other
#' genes
#' @param show.gene A vector of characters. It indicates which classes of genes
#' will be shown on the plot. Avaliable values are "nad|nd","sdh","cob",
#' "cox|cytb","atp", "ccmF","mtt","rps","rpl", "mat","orf","trn","rrn", "OTHER"
#' @param customize.ring1 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{position}: 1-base genomic coordinate for the features.
#'   \item \strong{value}: the values for the features.
#' }
#'
#' @param customize.ring1.type A character. It indicate the plot type in
#' customize.ring1. Available values are "line", "line + filling", "line + dot",
#' "line + dot + filling", "step line", "step line + filling", "vertical line"
#' @param customize.ring1.color An R color object. It indicates the color for
#' the plots in customized ring 1.
#' @param customize.ring2 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{position}: 1-base genome coordinate for the features.
#'   \item \strong{value}: the values for the features.
#' }
#' @param customize.ring2.type A character. It indicate the plot type in
#' customize.ring2. Available values are "line", "line + filling", "line + dot",
#' "line + dot + filling", "step line", "step line + filling", "vertical line"
#' @param customize.ring2.color An R color object. It indicates the color for
#' the plots in customized ring 2.
#' @param customize.ring3 A data frame. It must contain 2 columns:
#' \itemize{
#'   \item \strong{start}: 1-base genome coordinate for the start point of the
#'   features.
#'   \item \strong{end}: 1-base genome coordinate for the end point of the
#'   features.
#'   \item \strong{value}: the values for the features.
#' }
#' @param customize.ring3.color An R color object. It indicates the color for
#' the plots in customized ring 3.
#' @return  A plot for chloroplast genome.
#'
#' @references Supek, Fran, and Kristian Vlahovicek. “Comparison of codon usage
#' measures and their applicability in prediction of microbial gene
#' expressivity.” BMC bioinformatics vol. 6 182. 19 Jul.
#' 2005, doi:10.1186/1471-2105-6-182
#'
#' @importFrom magrittr %>%
#' @import dplyr
#' @export
PlotMitGenome2 <- function(plot.tables, save = TRUE, file.type = "pdf",
                          text.size = 1, height = c(0.1, 0.2, 0.07),
                          file.name = NULL,
                          gc.per.gene = TRUE, pseudo = TRUE, legend = TRUE,
                          genome.length = TRUE, total.gc = TRUE,
                          gene.no = TRUE, rrn.no = TRUE, trn.no = TRUE,
                          organelle_type = TRUE,
                          background = "grey90", gc.color = "grey30",
                          gc.background = "grey70", info.background = "black",
                          nad.color = "#2A6332", sdh.color = "#4C8805",
                          cob.color = "#7F992C", cox.color = "#FEEE50",
                          atp.color = "#9FBB3D", ccmF.color = "#4D9E3F",
                          mmt.color = "#AE2D29", rps.color = "#D6AD7C",
                          rpl.color = "#9C7A4B", mat.color = "#D9662D",
                          orf.color = "#71B8A9", trn.color = "#172C7F",
                          rrn.color = "#D1382A", other_gene.color = "#7D7D7D",
                          show.genes = c("nad|nd","sdh","cob","cox|cytb","atp",
                                         "ccmF","mtt","rps","rpl",
                                         "mat","orf","trn","rrn", "OTHER"),
                          cu.bias = TRUE, customize.ring1 = NULL,
                          customize.ring1.color = "grey30",
                          customize.ring1.type = "line",
                          customize.ring2.color = "grey30",
                          customize.ring2 = NULL,
                          customize.ring2.type = "line",
                          customize.ring3 = NULL,
                          customize.ring3.color = "grey30"){

  # Unpack plot.table
  genome <- plot.tables$genome
  gc_count <- plot.tables$gc_count
  gc_total <- plot.tables$gc_total
  sp_name <- plot.tables$sp_name
  gene_table <- plot.tables$gene_table
  genome <- plot.tables$genome

  l <- Biostrings::nchar(genome)

  # 1. Modify gene table

  # colouring
  color_table <- mitGeneColor(nad.color = nad.color, sdh.color = sdh.color,
                              cob.color = cob.color, cox.color = cox.color,
                              atp.color = atp.color, ccmF.color = ccmF.color,
                              mmt.color = mmt.color, rps.color = rps.color,
                              rpl.color = mmt.color, mat.color = mat.color,
                              orf.color = orf.color, trn.color = trn.color,
                              rrn.color = rrn.color,
                              other_gene.color = other_gene.color)


  gene_table <- dplyr::left_join(gene_table, color_table, by = c("class" = "acronym"))

  gene_table <- gene_table[which(gene_table$class %in% show.genes), ]

  color_table <- color_table[which(color_table$acronym %in% unique(gene_table$class)), ]

  # gene labels
  gene_table$gene_label <- gene_table$gene
  if (cu.bias){
    gene_table$gene_label <- apply(gene_table[, c("gene_label", "cu_bias")], 1,
                                   function(x){
                                     if (is.na(x[2])){
                                       return(x[1])
                                     } else {
                                       return(paste0(x[1], " (",
                                                     signif(as.numeric(x[2]), 2), ")"))
                                     }
                                   })
  }

  if (pseudo){
    gene_table$gene_label <- apply(gene_table[, c("gene_label", "pseudo")], 1,
                                   function(x){
                                     if (x[2]){
                                       return(paste0(x[1], " *"))
                                     } else {
                                       return(x[1])
                                     }
                                   })
  }
  genome <- genome
  gene_table_r <- filter(gene_table, strand == "-") %>%
    select(chr, start, end, gene, col, gc_count, gene_label) %>%
    arrange(start)
  gene_table_f <- filter(gene_table, strand == "+") %>%
    select(chr, start, end, gene, col, gc_count, gene_label) %>%
    arrange(start)

  # 2. Set colors
  # Automatically adjust colors
  info.color <- CompColor(info.background)

  # 3. Genome information
  n_trn <- sum(grepl("trn", gene_table$gene, perl = TRUE))
  n_rrn <- sum(grepl("rrn", gene_table$gene, perl = TRUE))
  n_gene <- nrow(gene_table) - n_trn - n_rrn

  # 4. Generate plot
  # Initialize the plot device
  if (save){
    if (is.null(file.name)){
      file <- sp_name
    } else {
      file <- file.name
    }
    if (!file.type %in% c("jpeg", "bmp", "png", "tiff", "pdf")){
      warning("Can not save plot in ", file.type, " format. Avaliable formats
                are 'jpeg', 'bmp', 'png', 'tiff',and 'pdf'.")
    } else if (file.type  == "pdf") {
      grDevices::pdf(paste(file, file.type, sep="."), width=10.3, height=8.9)
    } else {
      do.call(file.type, args=list(filename=paste(file, file.type, sep="."),
                                   width = 10.3, height = 8.9, units = "in",
                                   res = 1000))
    }
  }


  # Initialize the layout

  # Track indexes
  track_index <- 1:7
  names(track_index) <- c("gene out 1", "gene out 2", "gene", "gene inner 1",
                          "gene inner 2", "arrow", "gc count")

  if (!is.null(customize.ring1)){
    track_index[c("arrow", "gc count")] <- track_index[c("arrow", "gc count")] + 1
    track_index["customize 1"] <- track_index["gene inner 2"] + 1
  }

  if (!is.null(customize.ring2)){
    track_index[c("arrow", "gc count")] <- track_index[c("arrow", "gc count")] + 1
    track_index["customize 2"] <- track_index["arrow"] - 1
  }

  if (!is.null(customize.ring3)){
    track_index[c("arrow", "gc count")] <- track_index[c("arrow", "gc count")] + 1
    track_index["customize 3"] <- track_index["arrow"] - 1
  }

  # Track heights
  n_customize_ring <- sum(c(!is.null(customize.ring1), !is.null(customize.ring2), !is.null(customize.ring3)))
  if (n_customize_ring == 1){
    height[2] <- height[2]/1.5
  } else if (n_customize_ring == 2) {
    height[2] <- height[2]/2
    height[3] <- height[3] * 0.7
  } else if (n_customize_ring == 3) {
    height[2] <- height[2]/2
    height[3] <- height[3] * 0.7
    height[1] <- height[1] *0.7
  }


  circlize::circos.clear()
  circlize::circos.par(start.degree = 0, gap.after = 0,
                       track.margin = c(0, 0), cell.padding = c(0, 0, 0, 0))
  circlize::circos.genomicInitialize(data=data.frame(chr="chr1", start=0, end=l,
                                                     stringsAsFactors = FALSE),
                                     plotType = NULL)

  # 1.2. gene label outside
  if (nrow(gene_table_r) == 0 ) {
    # Background
    circlize::draw.sector(0, 360,
                          rou1 = 1,
                          rou2 = 0,
                          col = background, border = NA)
  } else {
    circlize::circos.genomicLabels(gene_table_r, labels = gene_table_r$gene_label,
                                   side = "outside",cex = 0.5 * text.size,
                                   connection_height = circlize::convert_height(3, "mm"),
                                   labels_height = max(graphics::strwidth(gene_table_r$gene_label,
                                                                          cex = 0.5 * text.size,
                                                                          font = graphics::par("font")))
    )
    # Background
    circlize::draw.sector(0, 360,
                          rou1 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                              track.index = 2),
                          rou2 = 0,
                          col = background, border = NA)
  }



  # 3. Gene rectangles
  if (nrow(gene_table_r) != 0 & nrow(gene_table_f) != 0) {
    circlize::circos.genomicTrack(gene_table_f, factors = as.factor("chr1"),
                                  ylim = c(-1, 1), bg.border = NA,
                                  track.height = height[1], #circlize::convert_height(10, "mm"),
                                  panel.fun = function(region, value, ...) {

                                    if(gc.per.gene){
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = - gene_table_f$gc_count,
                                        ytop = 0,
                                        col = gene_table_f$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_f$col, 0.7),
                                        border = NA
                                      )

                                      # genes lay on reverse chain
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = gene_table_r$gc_count,
                                        col = gene_table_r$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_r$col, 0.7),
                                        border = NA
                                      )
                                    } else {
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = gene_table_f$col
                                      )

                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = gene_table_r$col
                                      )
                                    }

                                    # the x axis
                                    circlize::circos.rect(xleft = 0,
                                                          ybottom = - 0.05,
                                                          xright = l,
                                                          ytop = 0.05,
                                                          col = "black",
                                                          border = NA)
                                  })
  } else if (nrow(gene_table_f) != 0){
    circlize::circos.genomicTrack(gene_table_f, factors = as.factor("chr1"),
                                  ylim = c(-1, 1), bg.border = NA,
                                  track.height = height[1], #circlize::convert_height(10, "mm"),
                                  panel.fun = function(region, value, ...) {

                                    if (gc.per.gene){
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = - gene_table_f$gc_count,
                                        ytop = 0,
                                        col = gene_table_f$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_f$col, 0.7),
                                        border = NA
                                      )
                                    } else {
                                      # genes lay on forward chain
                                      circlize::circos.genomicRect(
                                        gene_table_f[, c("start", "end")],
                                        value = gene_table_f$gene,
                                        ybottom = -1,
                                        ytop = 0,
                                        lwd = 0.5,
                                        col = gene_table_f$col
                                      )
                                    }
                                    # the x axis
                                    circlize::circos.rect(xleft = 0,
                                                          ybottom = - 0.05,
                                                          xright = l,
                                                          ytop = 0.05,
                                                          col = "black",
                                                          border = NA)
                                  })
    track_index[3:length(track_index)] <- track_index[3:length(track_index)] - 2
    track_index <- track_index[-which(names(track_index) %in% c("gene out 1", "gene out 2"))]
  } else if (nrow(gene_table_r) != 0) {
    circlize::circos.genomicTrack(gene_table_r, factors = as.factor("chr1"),
                                  ylim = c(-1, 1), bg.border = NA,
                                  track.height = height[1], #circlize::convert_height(10, "mm"),
                                  panel.fun = function(region, value, ...) {

                                    if(gc.per.gene){
                                      # genes lay on reverse chain
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = gene_table_r$gc_count,
                                        col = gene_table_r$col,
                                        border = NA)
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = Transparent(gene_table_r$col, 0.7),
                                        border = NA
                                      )
                                    } else {
                                      circlize::circos.genomicRect(
                                        gene_table_r[, c("start", "end")],
                                        value = gene_table_r$gene,
                                        ybottom = 0,
                                        ytop = 1,
                                        lwd = 0.5,
                                        col = gene_table_r$col
                                      )
                                    }

                                    # the x axis
                                    circlize::circos.rect(xleft = 0,
                                                          ybottom = - 0.05,
                                                          xright = l,
                                                          ytop = 0.05,
                                                          col = "black",
                                                          border = NA)
                                  })
    track_index[(which(names(track_index) == "gene inner 2") + 1):length(track_index)] <-
      track_index[(which(names(track_index) == "gene inner 2") + 1):length(track_index)] - 2
    track_index <- track_index[-which(names(track_index) %in% c("gene inner 1", "gene inner 2"))]
  } else {
    track_index <- track_index[6:length(track_index)] -5
  }

  # 4.5. gene labels inside
  if (nrow(gene_table_f) != 0){
    circlize::circos.genomicLabels(gene_table_f, labels = gene_table_f$gene_label,
                                   side = "inside", cex = 0.5 * text.size,
                                   connection_height = circlize::convert_height(3, "mm"),
                                   labels_height = max(graphics::strwidth(gene_table_f$gene_label,
                                                                          cex = 0.5 * text.size,
                                                                          font = graphics::par("font"))))
  }

  # customized ring 1
  if (!is.null(customize.ring1)) {
    customize.ring1 <- customize.ring1[order(customize.ring1$position), ]
    customize.ring1$chr <- rep("chr1", nrow(customize.ring1))
    ylim <- c(min(customize.ring1$value), max(customize.ring1$value))
    bar_color <- ifelse(customize.ring1$value > 0, "orangered3", "steelblue")
    if (min(customize.ring1$value) > 0) {
      ylim[1] <- 0
      bar_color <- rep(customize.ring1.color, nrow(customize.ring1))
    }
    if (max(customize.ring1$value) < 0){
      ylim[2] <- 0
      bar_color <- rep(customize.ring1.color, nrow(customize.ring1))
    }
    style <- switch(customize.ring1.type,
                    "line" = list(type = "l", arear = FALSE, col = customize.ring1.color, lwd = 0.5),
                    "line + filling" = list(type = "l", arear = TRUE, col = customize.ring1.color, lwd = 0.01),
                    "line + dot" = list(type = "o", arear = FALSE, col = bar_color, lwd = 0.5),
                    "line + dot + filling" = list(type = "o", arear = TRUE, col = bar_color, lwd = 0.01),
                    "step line" = list(type = "s", arear = FALSE, col = customize.ring1.color, lwd = 0.5),
                    "step line + filling" = list(type = "s", arear = TRUE, col = customize.ring1.color, lwd = 0.01),
                    "vertical line" = list(type = "h", arear = FALSE, col = bar_color, lwd = 0.5))

    circlize::circos.track(factors =as.factor(customize.ring1$chr),
                           x = customize.ring1$position,
                           y = customize.ring1$value, ylim = ylim,
                           track.height = height[2]/2,
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             circlize::circos.lines(x, y, type = style$type,
                                                    area = style$area,
                                                    baseline = 0,
                                                    pch = 1,
                                                    cex = 0.2 * text.size,
                                                    col = style$col,
                                                    lwd = style$lwd)
                             circlize::circos.segments(x0=0, x1=l, y0=0,
                                                       y1=0, lwd=0.5,
                                                       lty="16",
                                                       col=darken(customize.ring1.color, 0.7))
                           })

  }

  # customized ring 2
  if (!is.null(customize.ring2)) {
    customize.ring2 <- customize.ring2[order(customize.ring2$position), ]
    customize.ring2$chr <- rep("chr1", nrow(customize.ring2))
    ylim <- c(min(customize.ring2$value), max(customize.ring2$value))
    bar_color <- ifelse(customize.ring2$value > 0, "orangered3", "steelblue")
    if (min(customize.ring2$value) > 0) {
      ylim[1] <- 0
      bar_color <- rep(customize.ring2.color, nrow(customize.ring2))
    }
    if (max(customize.ring2$value) < 0){
      ylim[2] <- 0
      bar_color <- rep(customize.ring2.color, nrow(customize.ring2))
    }
    style <- switch(customize.ring2.type,
                    "line" = list(type = "l", arear = FALSE, col = customize.ring2.color, lwd = 0.5),
                    "line + filling" = list(type = "l", arear = TRUE, col = customize.ring2.color, lwd = 0.01),
                    "line + dot" = list(type = "o", arear = FALSE, col = bar_color, lwd = 0.5),
                    "line + dot + filling" = list(type = "o", arear = TRUE, col = bar_color, lwd = 0.01),
                    "step line" = list(type = "s", arear = FALSE, col = customize.ring2.color, lwd = 0.5),
                    "step line + filling" = list(type = "s", arear = TRUE, col = customize.ring2.color, lwd = 0.01),
                    "vertical line" = list(type = "h", arear = FALSE, col = bar_color, lwd = 0.5))

    circlize::circos.track(factors =as.factor(customize.ring2$chr),
                           x = customize.ring2$position,
                           y = customize.ring2$value, ylim = ylim,
                           track.height = height[2]/2,
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             circlize::circos.lines(x, y, type = style$type,
                                                    area = style$area,
                                                    baseline = 0,
                                                    pch = 1,
                                                    cex = 0.2 * text.size,
                                                    col = style$col,
                                                    lwd = style$lwd)
                             circlize::circos.segments(x0=0, x1=l, y0=0,
                                                       y1=0, lwd=0.5,
                                                       lty="16",
                                                       col=darken(customize.ring2.color, 0.7))
                           })

  }

  # customize.ring 3
  if (!is.null(customize.ring3)) {
    customize.ring3$chr <- rep("chr1", nrow(customize.ring3))
    ylim <- c(min(customize.ring3$value), max(customize.ring3$value))
    if (min(customize.ring3$value) > 0) {
      ylim[1] <- 0
    }
    if (max(customize.ring3$value) < 0){
      ylim[2] <- 0
    }
    circlize::circos.track(factors =as.factor(customize.ring3$chr),
                           track.margin = c(0, circlize::convert_height(1, "mm")),
                           track.height = height[2]/2,
                           ylim = ylim,
                           bg.border = NA, bg.col = gc.background,
                           panel.fun = function(x, y) {
                             if (min(customize.ring3$value) < 0 &
                                 max(customize.ring3$value) > 0) {
                               df_large <- customize.ring3[which(customize.ring3$value > 0), ]
                               df_less <- customize.ring3[which(customize.ring3$value < 0), ]
                               circlize::circos.rect(xleft = df_large$start,
                                                     xright = df_large$end,
                                                     ybottom = 0,
                                                     ytop = df_large$value,
                                                     col = "orangered3",
                                                     border = NA)
                               circlize::circos.rect(xleft = df_less$start,
                                                     xright = df_less$end,
                                                     ybottom = df_less$value,
                                                     ytop = 0,
                                                     col = "steelblue",
                                                     border = NA)
                             } else if (min(customize.ring3$value) < 0) {
                               circlize::circos.rect(xleft = customize.ring3$start,
                                                     xright = customize.ring3$end,
                                                     ybottom = customize.ring3$value,
                                                     ytop = 0,
                                                     col = customize.ring3.color,
                                                     border = NA)
                             } else {
                               circlize::circos.rect(xleft = customize.ring3$start,
                                                     xright = customize.ring3$end,
                                                     ybottom = 0,
                                                     ytop = customize.ring3$value,
                                                     col = customize.ring3.color,
                                                     border = NA)
                             }
                           })
  }
  # 6. Arrow outside gnome axis
  circlize::circos.track(ylim = c(0, 1), track.height = 0.06, bg.border = NA,
                         track.margin = c(0, circlize::convert_height(1, "mm")),
                         panel.fun = function(x, y) {
                           circlize::circos.arrow(x1 = l - l %/% 40,
                                                  x2 = l,
                                                  y = 0.85,
                                                  arrow.position="start",
                                                  col = MildColor(background),
                                                  border = NA,
                                                  arrow.head.length = circlize::convert_x(3, "mm"),
                                                  width = 0.15)
                           # circlize::circos.genomicAxis(h = "bottom")
                         })



  # 7. GC content
  circlize::circos.track(factors =as.factor(gc_count$chr),
                         x=gc_count$position,
                         y = 1- gc_count$gc_count,
                         ylim = c(0, 1),
                         track.height = height[2],
                         bg.border = NA, bg.col = gc.background,
                         panel.fun = function(x, y) {
                           circlize::circos.lines(x, y, type = "s", area = TRUE,
                                                  baseline = "top",
                                                  col = gc.color, lwd = 0.00001)
                           circlize::circos.arrow(x1= 0,
                                                  x2= l %/% 35,
                                                  y= 0.9,
                                                  col=MildColor(gc.color),
                                                  border=NA,
                                                  arrow.head.length=circlize::convert_x(3, "mm"),
                                                  width=0.15 * 0.05 / height[2])
                           circlize::circos.segments(x0=0, x1=l, y0=0.25,
                                                     y1=0.25, lwd=0.5,
                                                     lty="16", col=MildColor(gc.background))
                           circlize::circos.segments(x0=0, x1=l, y0=0.5,
                                                     y1=0.5, lwd=0.6,
                                                     lty="11", col=MildColor(gc.background))
                           circlize::circos.segments(x0=0, x1=l, y0=0.75,
                                                     y1=0.75, lwd=0.5,
                                                     lty="16", col=MildColor(gc.color))
                           circlize::circos.genomicAxis(h = "top", labels.cex = 0.4 * text.size)
                         })
  #circos.yaxis(at=c(0.25,0.5,0.75),labels.cex=0.25 * text.size,lwd=0,tick.length=0,
  #             labels.col="grey40",col="#FFFFFF")

  # Specie's information inthe central
  circlize::draw.sector(0, 360,
                        rou1 = circlize::get.cell.meta.data("cell.bottom.radius",
                                                            track.index = track_index['gc count']),
                        rou2 = 0,
                        col = info.background, border = NA)

  if (organelle_type){
    graphics::text(0,0.10, sp_name, font=4, cex = 0.8 * text.size, col = info.color)
    graphics::text(0,0.05, "Plastid Genome", font=4, cex = 0.8 * text.size, col = info.color)
  } else{
    graphics::text(0,0.05, sp_name, font=4, cex = 0.8 * text.size, col = info.color)
  }

  ns <- c(paste(n_gene, "genes"), paste(n_rrn, "rRNAs"), paste(n_trn, "tRNAs"))[which(c(gene.no, rrn.no, trn.no))]
  text <- c(paste(ns, collapse = "; "), paste(prettyNum(l, big.mark = ","), "bp", " "),
            paste("GC:",round(gc_total, 2)*100,"%"))
  j <- 1
  if (cu.bias){
    cex = 0.7 * text.size
  } else {
    cex = 0.8 * text.size
  }
  for (i in which(c((length(ns) != 0), genome.length, total.gc))) {
    graphics::text(0,0.05 - 0.05 * j, text[i],
                   font=4, cex = cex, col = info.color)
    j <-  j + 1
  }

  # Highlight IR

  # Add legend
  if (legend){
    legend(x = -1.27, y = -0.6, legend = color_table$label, cex = 0.6 * text.size,
           fill = color_table$col, bg = rgb(255, 255, 255, alpha = 0, maxColorValue = 255),
           box.col = rgb(255, 255, 255, alpha = 0, maxColorValue = 255))
  }

  if (save){
    grDevices::dev.off()
  }

}

# GC_count.R

gc_count <- function(genome, view.width = 10){
  n <- Biostrings::nchar(genome)
  genome <- c(genome, genome[1:view.width])
  count <- as.vector(Biostrings::letterFrequencyInSlidingView(genome,
                                                    letters = "GC",
                                                    view.width = view.width))
  total <- as.vector(Biostrings::letterFrequency(genome, letters = "GC"))/n
  res <- data.frame(position = seq(1, n+1),
                    gc_count = count/view.width,
                    stringsAsFactors = FALSE)
  res <- res[c(seq(1, n, by = view.width), n), ]
  res <- list(gc_count_table = res, total_count = total)
  return(res)
}

gc_count_gene <- function(genome, gene_table){
  genes <- Biostrings::DNAStringSet(genome, start = gene_table$start,
                                    end = gene_table$end)
  gc_genes <- as.vector(Biostrings::letterFrequency(genes, letters = "GC"))
  len_genes <- Biostrings::nchar(genes)
  gene_table$gc_count <- gc_genes/len_genes
  return(gene_table)
}

gc_count_ir <- function(genome, ir_table){
  genes <- Biostrings::DNAStringSet(genome, start = ir_table$start + 1,
                                    end = ir_table$end)
  gc_genes <- as.vector(Biostrings::letterFrequency(genes, letters = "GC"))
  len_genes <- Biostrings::nchar(genes)
  if (nrow(ir_table) == 5) {
    gc_genes[1] <- gc_genes[5] <- gc_genes[1] + gc_genes[5]
    len_genes[1] <- len_genes[5] <- len_genes[1] + len_genes[5]
    ir_table$gc_count <- gc_genes/len_genes
  } else {
    ir_table$gc_count <- gc_genes/len_genes
  }
  return(ir_table)
}

# t1 <- PlotTab2(gbfile = "~/all/polap/github/src/NC_012920.1.gb", local.file = TRUE, gc.window = 100)
# y1 <- read_tsv("~/all/polap/github/src/annotation.bed", col_names = FALSE)
# x1 <- readDNAStringSet("~/all/polap/github/src/mt.3.fa")
g1 <- x1[[1]]
l1 <- Biostrings::nchar(g1)

gc.window <- 200
if (l1 > 500000){
  gc.window <- 200
} else if (l1 < 100000){
  gc.window <- 50
}

gc_count_list <- gc_count(g1, view.width = gc.window)
gc_count <- gc_count_list[[1]]
gc_total <- gc_count_list[[2]]
gc_count$chr <- rep("chr1", nrow(gc_count))
gc_count <- select(gc_count, chr, position, gc_count)

gt1 <- data.frame(
  chr = rep("chr1", nrow(y1)),
  start = y1$X2,
  end = y1$X3,
  gene = y1$X4,
  strand = rep("+", nrow(y1)),
  pseudo = rep(FALSE, nrow(y1)),
  cu_bias = rep(NA, nrow(y1)),
  gc_count = rep(0.5, nrow(y1)),
  class = rep("OTHER", nrow(y1))
)

t2 <- list(ir_table = NULL, indel_table = NULL,
           gc_count = gc_count, 
           gc_total = gc_total, 
           plastid = FALSE,
           sp_name = "mt.3", 
           genome_len = l1, 
           gene_table = gt1,
           genome = g1)

PlotMitGenome(t2) # The plot will be saved in a pdf file under your work directory.
