# The MIT License (MIT)

# Copyright (c) 2023 Mike DeAngelo Google, Inc.

# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# frozen_string_literal: true

require_relative '../../command'
require_relative '../../modules/folder'
require 'tty-tree'

# The tty-tree tool is built on the idea of handling directories, so it does
# parsing based on slashs (or backslashs on Windows). If those characters are
# in object names, tty-tree pulls them out.
# This monkey patch disables that.

module TTY
  class Tree
    class Node
      def initialize(path, parent, prefix, level)
        if path.is_a? String
          # strip null bytes from the string to avoid throwing errors
          path = path.delete("\0")
        end

        @path = path
        @name   = path
        @parent = parent
        @prefix = prefix
        @level  = level
      end
    end
  end
end

module Gzr
  module Commands
    class Folder
      class Tree < Gzr::Command
        include Gzr::Folder
        def initialize(filter_spec, options)
          super()
          @filter_spec = filter_spec
          @options = options
        end

        def execute(input: $stdin, output: $stdout)
          say_warning("options: #{@options.inspect}") if @options[:debug]
          with_session do
            folder_ids = process_args([@filter_spec])

            tree_data = Hash.new

            folder_ids.each do |folder_id|
              s = query_folder(folder_id, "id,name,parent_id,looks(id,title),dashboards(id,title)")
              folder_name = s[:name]
              folder_name = "nil (#{s[:id]})" unless folder_name
              folder_name = "\"#{folder_name}\"" if ((folder_name != folder_name.strip) || (folder_name.length == 0))
              folder_name += " (#{folder_id})" unless folder_ids.length == 1
              tree_data[folder_name] =
                [ recurse_folders(s[:id]) ] +
                s[:looks].map { |l| "(l) #{l[:title]}" } +
                s[:dashboards].map { |d| "(d) #{d[:title]}" }
            end
            tree = TTY::Tree.new(tree_data)
            output.puts tree.render
          end
        end

        def recurse_folders(folder_id)
          data = query_folder_children(folder_id, "id,name,parent_id,looks(id,title),dashboards(id,title)")
          tree_branch = Hash.new
          data.each do |s|
            folder_name = s[:name]
            folder_name = "nil (#{s[:id]})" unless folder_name
            folder_name = "\"#{folder_name}\"" if ((folder_name != folder_name.strip) || (folder_name.length == 0))
            tree_branch[folder_name] =
              [ recurse_folders(s[:id]) ] +
              s[:looks].map { |l| "(l) #{l[:title]}" } +
              s[:dashboards].map { |d| "(d) #{d[:title]}" }
          end
          tree_branch
        end
      end
    end
  end
end
