# dir_collection ---------------------------------------------------------
dir_collection <- R6Class(
  "dir_collection",
  public = list(
    initialize = function(package_dir, container) {
      dir_ <- file.path(package_dir, container$dir_name())
      private$package_dir <- package_dir
      filenames <- list.files(
        path = dir_,
        pattern = "\\.xml$",
        full.names = TRUE
      )
      filenames <- sort_vec_by_index(filenames) # see issue #596
      private$collection <- lapply(
        filenames,
        function(x, container) {
          container$clone()$feed(x)
        },
        container = container
      )
      names(private$collection) <- basename(filenames)
    },

    collection_get = function(name) {
      private$collection[[name]]
    },

    get_metadata = function() {
      dat <- lapply(private$collection, function(x) x$get_metadata())
      rbind_match_columns(dat)
    },
    names = function() {
      sapply(private$collection, function(x) x$name())
    },
    xfrm = function() {
      dat <- lapply(private$collection, function(x) x$xfrm())
      do.call(rbind, dat)
    }
  ),

  private = list(
    collection = NULL,
    package_dir = NULL
  )
)


# dir_layout ---------------------------------------------------------
dir_layout <- R6Class(
  "dir_layout",
  inherit = dir_collection,
  public = list(
    initialize = function(package_dir, master_metadata, master_xfrm) {
      super$initialize(package_dir, slide_layout$new("ppt/slideLayouts"))
      private$master_metadata <- master_metadata
      private$xfrm_data <- xfrmize(self$xfrm(), master_xfrm)
    },

    get_xfrm_data = function() {
      private$xfrm_data
    },

    get_metadata = function() {
      data_layouts <- super$get_metadata()
      data_masters <- private$master_metadata
      data_masters$master_file <- basename(data_masters$filename)
      data_masters$filename <- NULL
      data_layouts$master_file <- basename(data_layouts$master_file)
      out <- merge(data_layouts, data_masters, by = "master_file", all = FALSE)
      out$filename <- basename(out$filename)
      out
    }
  ),
  private = list(
    master_collection = NULL,
    master_metadata = NULL,
    xfrm_data = NULL
  )
)


# dir_slide ---------------------------------------------------------
dir_slide <- R6Class(
  "dir_slide",
  inherit = dir_collection,
  public = list(
    initialize = function(package_dir, xfrm_layout_data) {
      super$initialize(package_dir, slide$new("ppt/slides"))
      private$collection <- lapply(
        private$collection,
        function(x, ref) x$set_layout_xfrm(ref),
        ref = xfrm_layout_data
      )
      names(private$collection) <- sapply(private$collection, function(x) {
        x$name()
      })
      private$slides_list <- private$get_slide_list()
    },

    add_slide = function(slide_file, xfrm_layout_data) {
      slide <- slide$new("ppt/slides")
      slide$feed(slide_file)
      slide$set_layout_xfrm(xfrm_layout_data)

      collect <- private$collection
      new_elt <- list(slide)
      names(new_elt) <- basename(slide_file)
      collect <- append(collect, new_elt)

      sl_id <- as.integer(gsub(
        "(slide)([0-9]+)(\\.xml)$",
        "\\2",
        names(collect)
      ))
      private$collection <- collect[order(sl_id)]
      private$slides_list <- names(private$collection)

      self
    },
    slide_index = function(name) {
      which(private$slides_list %in% name)
    },

    remove_slide = function(index) {
      slide_obj <- private$collection[[index]]
      private$collection <- private$collection[-index]
      private$slides_list <- names(private$collection)
      slide_obj$remove()
    },

    save_slides = function() {
      lapply(private$collection, function(x) {
        x$save()
      })
      self
    },

    get_xfrm = function() {
      lapply(private$collection, function(x) x$get_xfrm())
    },

    get_slide = function(id) {
      l_ <- self$length()
      if (is.null(id) || !between(id, 1, l_)) {
        stop("unvalid id ", id, " (", l_, " slide(s))", call. = FALSE)
      }
      index <- which(names(private$collection) == private$slides_list[id])
      private$collection[[index]]
    },

    get_metadata = function() {
      super$get_metadata()
    },

    length = function() {
      length(private$collection)
    },

    get_new_slidename = function() {
      slide_dir <- file.path(private$package_dir, "ppt/slides")
      if (!file.exists(slide_dir)) {
        dir.create(
          file.path(slide_dir, "_rels"),
          showWarnings = FALSE,
          recursive = TRUE
        )
      }

      slide_files <- names(private$collection)
      slidename <- "slide1.xml"
      if (length(slide_files)) {
        slide_index <- as.integer(gsub(
          "^(slide)([0-9]+)(\\.xml)$",
          "\\2",
          slide_files
        ))
        slidename <- gsub(
          pattern = "[0-9]+",
          replacement = max(slide_index) + 1,
          slidename
        )
      }
      slidename
    }
  ),
  private = list(
    slides_list = NULL,

    get_slide_list = function() {
      slide_dir <- file.path(private$package_dir, "ppt/slides")
      slide_files <- list.files(slide_dir, pattern = "\\.xml$")
      slide_index <- seq_along(slide_files)
      if (length(slide_files)) {
        slide_files <- basename(slide_files)
        slide_index <- as.integer(gsub(
          "^(slide)([0-9]+)(\\.xml)$",
          "\\2",
          slide_files
        ))
        slide_files <- slide_files[order(slide_index)]
      }
      slide_files
    }
  )
)


# dir_master ---------------------------------------------------------

dir_master <- R6Class(
  "dir_master",
  inherit = dir_collection,
  public = list(
    get_metadata = function() {
      unames <- sapply(private$collection, function(x) x$name())
      ufnames <- sapply(private$collection, function(x) x$file_name())
      data.frame(
        stringsAsFactors = FALSE,
        master_name = unames,
        filename = ufnames
      )
    },
    get_color_scheme = function() {
      dat <- lapply(private$collection, function(x) x$colors())
      rbind_match_columns(dat)
    }
  )
)

# dir_notesMaster ---------------------------------------------------------

dir_notesMaster <- R6Class(
  "dir_notesMaster",
  inherit = dir_collection,
  public = list(
    get_metadata = function() {
      unames <- sapply(private$collection, function(x) x$name())
      ufnames <- sapply(private$collection, function(x) x$file_name())
      data.frame(
        stringsAsFactors = FALSE,
        master_name = unames,
        filename = ufnames
      )
    },

    add_notesMaster = function(file) {
      nmaster <- slide_master$new("ppt/notesMasters")
      nmaster$feed(file)

      collect <- private$collection
      new_elt <- list(nmaster)
      names(new_elt) <- basename(file)
      collect <- append(collect, new_elt)

      sl_id <- as.integer(gsub(
        "(notesMaster)([0-9]+)(\\.xml)$",
        "\\2",
        names(collect)
      ))
      private$collection <- collect[order(sl_id)]

      self
    }
  )
)


# dir_notesSlide ---------------------------------------------------------
dir_notesSlide <- R6Class(
  "dir_notesSlide",
  inherit = dir_collection,
  public = list(
    initialize = function(package_dir) {
      super$initialize(package_dir, notesSlide$new("ppt/notesSlides"))
    },

    add_slide = function(slide_file) {
      nslide <- notesSlide$new("ppt/notesSlides")
      nslide$feed(slide_file)

      collect <- private$collection
      new_elt <- list(nslide)
      names(new_elt) <- basename(slide_file)
      collect <- append(collect, new_elt)

      sl_id <- as.integer(gsub(
        "(notesSlide)([0-9]+)(\\.xml)$",
        "\\2",
        names(collect)
      ))
      private$collection <- collect[order(sl_id)]

      self
    },
    slide_index = function(name) {
      which(names(private$collection) %in% name)
    },

    remove_slide = function(index) {
      slide_obj <- private$collection[[index]]
      private$collection <- private$collection[-index]
      slide_obj$remove()
    },

    save_slides = function() {
      lapply(private$collection, function(x) {
        x$save()
      })
      self
    },

    get_slide = function(id) {
      l_ <- self$length()
      if (is.null(id) || !between(id, 1, l_)) {
        stop("unvalid id ", id, " (", l_, " slide(s))", call. = FALSE)
      }
      private$collection[[id]]
    },

    get_metadata = function() {
      super$get_metadata()
    },

    length = function() {
      length(private$collection)
    },

    get_new_slidename = function() {
      slide_dir <- file.path(private$package_dir, "ppt/notesSlides")
      if (!file.exists(slide_dir)) {
        dir.create(
          file.path(slide_dir, "_rels"),
          showWarnings = FALSE,
          recursive = TRUE
        )
      }

      slide_files <- names(private$collection)
      slidename <- "notesSlide1.xml"
      if (length(slide_files)) {
        slide_index <- as.integer(gsub(
          "^(notesSlide)([0-9]+)(\\.xml)$",
          "\\2",
          slide_files
        ))
        slidename <- gsub(
          pattern = "[0-9]+",
          replacement = max(slide_index) + 1,
          slidename
        )
      }
      slidename
    }
  )
)
