module GG_CabinetTools
  Dir.mkdir(CORE_DIR) unless File.directory?(CORE_DIR)

  rgloader_path = File.join(CORE_DIR, "rgloader", "loader.rb")
  load rgloader_path if File.exist?(rgloader_path)

  load_core = ->(name) {
    rbe = File.join(CORE_DIR, "#{name}.rbe")
    rb  = File.join(CORE_DIR, "#{name}.rb")
    path = File.exist?(rbe) ? rbe : rb
    load path if File.exist?(path)
  }

  load_core.call("util")
  load_core.call("locale")
  load_core.call("tool_commands")
  load_core.call("api")

  load_core.call("warehouse_store")

  load_core.call("solid_operations")
  load_core.call("abf_selector")

  core_skip_bases = %w[util locale tool_commands api warehouse_store checksums manifest item_upload item_download watcher warehouse_cable solid_operations unfold_settings_normalize tenon_helper_tool].freeze
  core_skip = core_skip_bases.flat_map { |b| ["#{b}.rb", "#{b}.rbe"] }.freeze
  Dir.glob(File.join(CORE_DIR, "**", "*.{rb,rbe}")).each do |f|
    basename = File.basename(f)
    next if core_skip.include?(basename)
    load f
  end

  unless file_loaded?(__FILE__)
    tc = GG_CabinetTools::ToolCommands
    toolbar_main = UI::Toolbar.new("GG Cabinet Tools")

    cmd_cnc_relief = tc.build(:cnc_relief) { run_if_signed_in { GG_CabinetTools::CNCReliefCircles.run_tool } }
    tc.set_icon(cmd_cnc_relief, "CNC_RELIEF.svg")
    toolbar_main.add_item(cmd_cnc_relief)

    cmd_tenon = tc.build(:tenon_helper) { run_if_signed_in { GG_CabinetTools::TenonMortise.run } }
    tc.set_icon(cmd_tenon, "TENON_HELPER.svg")
    toolbar_main.add_item(cmd_tenon)

    cmd_cam_lock = tc.build(:cam_lock) { run_if_signed_in { GG_CabinetTools::CamLock.run } }
    tc.set_icon(cmd_cam_lock, "CAM_LOCK.svg")
    toolbar_main.add_item(cmd_cam_lock)

    cmd_unsolid_trim = tc.build(:unsolid_trim) { run_if_signed_in { GG_CabinetTools::UnsolidTrim.run } }
    tc.set_icon(cmd_unsolid_trim, "UNSOLID_TRIM.svg")
    toolbar_main.add_item(cmd_unsolid_trim)

    cmd_unsolid_outer_shell = tc.build(:unsolid_outer_shell) { run_if_signed_in { GG_CabinetTools::UnsolidOuterShell.run } }
    tc.set_icon(cmd_unsolid_outer_shell, "UNSOLID_OUTER_SHELL.svg")
    toolbar_main.add_item(cmd_unsolid_outer_shell)

    cmd_intersect_mark = tc.build(:intersect_mark) { run_if_signed_in { GG_CabinetTools::IntersectMark.run } }
    tc.set_icon(cmd_intersect_mark, "INTERSECT_MARK.svg")
    toolbar_main.add_item(cmd_intersect_mark)

    cmd_warehouse = tc.build(:warehouse) do
      run_if_signed_in do
        GG_CabinetTools.show_warehouse_dialog if GG_CabinetTools.respond_to?(:show_warehouse_dialog)
      end
    end

    cmd_bend = tc.build(:bend) { run_if_signed_in { BendTool.run } }
    tc.set_icon(cmd_bend, "BEND.svg")
    toolbar_main.add_item(cmd_bend)

    cmd_unfold = tc.build(:unfold) { run_if_signed_in { UnfoldTool.run } }
    tc.set_icon(cmd_unfold, "UNFOLD.svg")
    toolbar_main.add_item(cmd_unfold)

    cmd_khau = tc.build(:khau) { run_if_signed_in { CrossHalvingJoinTool.run } }
    tc.set_icon(cmd_khau, "CROSS_HALVING_JOIN.svg")
    toolbar_main.add_item(cmd_khau)

    cmd_marking = tc.build(:marking) { run_if_signed_in { MarkingTool.run } }
    tc.set_icon(cmd_marking, "MARKING.svg")
    toolbar_main.add_item(cmd_marking)

    cmd_edge_band = tc.build(:edge_band) { run_if_signed_in { GG_CabinetTools::EdgeBand.run } }
    tc.set_icon(cmd_edge_band, "EDGE_BAND.svg")
    toolbar_main.add_item(cmd_edge_band)

    cmd_clone_board = tc.build(:clone_board) { run_if_signed_in { CloneBoardTool.run } }
    tc.set_icon(cmd_clone_board, "CLONE_BOARD.svg")
    toolbar_main.add_item(cmd_clone_board)

    cmd_face_offset = tc.build(:face_offset) { run_if_signed_in { FaceOffsetTool.run } }
    tc.set_icon(cmd_face_offset, "FACE_OFFSET.svg")
    toolbar_main.add_item(cmd_face_offset)

    cmd_move_vertices = tc.build(:move_vertices) { run_if_signed_in { GG_CabinetTools::MoveVerticesTool.run } }
    tc.set_icon(cmd_move_vertices, "MOVE_VERTICES.svg")
    toolbar_main.add_item(cmd_move_vertices)

    cmd_align = tc.build(:align) { run_if_signed_in { GG_CabinetTools::AlignTool.run } }
    tc.set_icon(cmd_align, "ALIGN.svg")
    toolbar_main.add_item(cmd_align)

    cmd_board_trim = tc.build(:board_trim) { run_if_signed_in { GG_CabinetTools::BoardTrimTool.run } }
    tc.set_icon(cmd_board_trim, "BOARD_TRIM.svg")
    toolbar_main.add_item(cmd_board_trim)

    cmd_vertex_slide = tc.build(:vertex_slide) { run_if_signed_in { GG_CabinetTools::VertexSlideTool.run } }
    tc.set_icon(cmd_vertex_slide, "VERTEX_SLIDE.svg")
    toolbar_main.add_item(cmd_vertex_slide)

    cmd_board_seeding = tc.build(:board_seeding) { run_if_signed_in { GG_CabinetTools::BoardSeedingTool.run } }
    tc.set_icon(cmd_board_seeding, "BOARD_SEEDING.svg")
    toolbar_main.add_item(cmd_board_seeding)

    cmd_cross_cut = tc.build(:cross_cut) { run_if_signed_in { CrossCutTool.run } }
    tc.set_icon(cmd_cross_cut, "CROSS_CUT.svg")
    toolbar_main.add_item(cmd_cross_cut)

    cmd_abf = tc.build(:abf_selector) { run_if_signed_in { GG_CabinetTools::ABFSelector.run } }
    tc.set_icon(cmd_abf, "ABF_SELECTOR.svg")
    toolbar_main.add_item(cmd_abf)

    cmd_fuzzy = tc.build(:fuzzy_finder) { run_if_signed_in { GG_CabinetTools::FuzzyInstanceFinder.show } }
    tc.set_icon(cmd_fuzzy, "FUZZY_FINDER.svg")
    toolbar_main.add_item(cmd_fuzzy)

    cmd_layer_sel = tc.build(:layer_manager) { run_if_signed_in { GG_CabinetTools::LayerManager.run } }
    tc.set_icon(cmd_layer_sel, "LAYER_MANAGER.svg")
    toolbar_main.add_item(cmd_layer_sel)

    cmd_nesting_move = tc.build(:nesting_move) { run_if_signed_in { GG_CabinetTools::NestingMoveTool.run_tool } }
    tc.set_icon(cmd_nesting_move, "NESTING_MOVE.svg")
    toolbar_main.add_item(cmd_nesting_move)

    cmd_rotate_label = tc.build(:rotate_label) { run_if_signed_in { GG_CabinetTools::ABFRotateLabel.run } }
    tc.set_icon(cmd_rotate_label, "ROTATE_LABEL.svg")
    toolbar_main.add_item(cmd_rotate_label)

    cmd_flip_label = tc.build(:flip_label) { run_if_signed_in { GG_CabinetTools::ABFFlipLabelFace.run } }
    tc.set_icon(cmd_flip_label, "FLIP_LABEL.svg")
    toolbar_main.add_item(cmd_flip_label)

    cmd_abf_extra_label = tc.build(:abf_extra_label) { run_if_signed_in { GG_CabinetTools::ABFExtraLabel.run } }
    tc.set_icon(cmd_abf_extra_label, "ABF_EXTRA_LABEL.svg")
    toolbar_main.add_item(cmd_abf_extra_label)

    cmd_abf_extra_nesting = tc.build(:abf_extra_nesting) { run_if_signed_in { GG_CabinetTools::ABFExtraNesting.run } }
    tc.set_icon(cmd_abf_extra_nesting, "ABF_EXTRA_NESTING.svg")
    toolbar_main.add_item(cmd_abf_extra_nesting)

    cmd_nesting_dxf = tc.build(:nesting_dxf) { run_if_signed_in { GG_CabinetTools::NestingDxfExport.run } }
    tc.set_icon(cmd_nesting_dxf, "NESTING_DXF.svg")
    toolbar_main.add_item(cmd_nesting_dxf)

    cmd_label_print = tc.build(:label_print) do
      run_if_signed_in do
        if GG_CabinetTools.respond_to?(:show_label_print_dialog)
          GG_CabinetTools.show_label_print_dialog
        else
          UI.messagebox("Label printing module is not available in this plugin install.")
        end
      end
    end
    tc.set_icon(cmd_label_print, "LABEL_PRINT.svg")
    toolbar_main.add_item(cmd_label_print)

    cmd_gcode = tc.build(:gcode) { run_if_signed_in { GcodeManager.run } }
    tc.set_icon(cmd_gcode, "GCODE.svg")
    toolbar_main.add_item(cmd_gcode)

    tc.set_icon(cmd_warehouse, "WAREHOUSE.svg")
    toolbar_main.add_item(cmd_warehouse)

    cmd_settings = tc.build(:settings) do
      run_if_signed_in do
        if GG_CabinetTools.respond_to?(:show_settings)
          show_settings
        else
          UI.messagebox("Settings module is not available in this plugin install.")
        end
      end
    end
    tc.set_icon(cmd_settings, "GEAR.svg")
    toolbar_main.add_item(cmd_settings)

    cmd_isolate = tc.build(:isolate) { run_if_signed_in { IsolateSelectionTool.run } }
    tc.set_icon(cmd_isolate, "ISOLATE.svg")
    toolbar_main.add_item(cmd_isolate)

    cmd_color = tc.build(:color) { run_if_signed_in { ColorTool.run } }
    tc.set_icon(cmd_color, "COLOR_PICKER.svg")
    toolbar_main.add_item(cmd_color)

    cmd_remove_color = tc.build(:remove_color) { run_if_signed_in { RemoveColorTool.run } }
    tc.set_icon(cmd_remove_color, "REMOVE_COLOR.svg")
    toolbar_main.add_item(cmd_remove_color)

    cmd_scale = tc.build(:dumb_scale) { run_if_signed_in { DumbScale.run } }
    tc.set_icon(cmd_scale, "SCALE.svg")
    toolbar_main.add_item(cmd_scale)

    cmd_hover_dimensions = tc.build(:hover_dimensions) { run_if_signed_in { HoverDimensionsTool.run } }
    tc.set_icon(cmd_hover_dimensions, "HOVER_DIMENSIONS.svg")
    toolbar_main.add_item(cmd_hover_dimensions)

    if admin?
      cmd_entity_dump = tc.build(:entity_dump) { run_if_admin { GG_CabinetTools::EntityConsoleDump.dump_selection_to_console } }
      tc.set_icon(cmd_entity_dump, "ENTITY_DUMP.svg")
      toolbar_main.add_item(cmd_entity_dump)

      cmd_entity_txt = tc.build(:entity_dump_txt) { run_if_admin { GG_CabinetTools::EntityConsoleDump.dump_selection_to_txt_interactive } }
      tc.set_icon(cmd_entity_txt, "ENTITY_DUMP_TXT.svg")
      toolbar_main.add_item(cmd_entity_txt)

      cmd_entity_json = tc.build(:entity_dump_json) { run_if_admin { GG_CabinetTools::EntityConsoleDump.dump_selection_to_json_interactive } }
      tc.set_icon(cmd_entity_json, "ENTITY_DUMP_JSON.svg")
      toolbar_main.add_item(cmd_entity_json)
    end

    toolbar_main.show
    toolbar_main.show

    menu = UI.menu("Plugins").add_submenu("GG Cabinet Tools")
    menu.add_item(cmd_scale)
    menu.add_item(cmd_hover_dimensions)
    menu.add_item(cmd_bend)
    menu.add_item(cmd_unfold)
    menu.add_item(cmd_khau)
    menu.add_item(cmd_marking)
    menu.add_item(cmd_clone_board)
    menu.add_item(cmd_face_offset)
    menu.add_item(cmd_vertex_slide)
    menu.add_item(cmd_board_seeding)
    # These tools live in the menu (not just the toolbar) so they can be bound to
    # keyboard shortcuts — SketchUp only lets you assign hotkeys to menu items.
    menu.add_item(cmd_align)
    menu.add_item(cmd_move_vertices)
    menu.add_item(cmd_board_trim)
    menu.add_item(cmd_color)
    menu.add_item(cmd_remove_color)
    menu.add_item(cmd_isolate)
    menu.add_item(cmd_cross_cut)
    menu.add_item(cmd_abf)
    menu.add_item(cmd_cnc_relief)
    menu.add_item(cmd_tenon)
    menu.add_item(cmd_cam_lock)
    menu.add_item(cmd_unsolid_trim)
    menu.add_item(cmd_unsolid_outer_shell)
    menu.add_item(cmd_intersect_mark)
    menu.add_item(cmd_fuzzy)
    menu.add_item(cmd_layer_sel)
    menu.add_item(cmd_gcode)
    menu.add_separator
    menu.add_item(cmd_abf_extra_label)
    menu.add_item(cmd_abf_extra_nesting)
    menu.add_item(cmd_rotate_label)
    menu.add_item(cmd_flip_label)
    menu.add_item(cmd_nesting_move)
    menu.add_item(cmd_nesting_dxf)
    menu.add_item(cmd_label_print)
    if admin?
      menu.add_separator
      menu.add_item(cmd_entity_dump)
      menu.add_item(cmd_entity_txt)
      menu.add_item(cmd_entity_json)
    end
    menu.add_separator

    menu.add_item(cmd_settings)
    menu.add_item(cmd_warehouse)
    menu.add_item(cmd_gcode)
    menu.add_separator
    cmd_sign_out = tc.build(:sign_out) { do_sign_out }
    menu.add_item(cmd_sign_out)

    UI.add_context_menu_handler do |context_menu|
      sel = Sketchup.active_model.selection
      next if sel.nil? || sel.empty?
      context_menu.add_separator
      context_menu.add_item(tc.name(:ctx_remove_material)) do
        RemoveColorTool.run
      end
    end

    GG_CabinetTools::EntityConsoleDump.register_context_menu! if GG_CabinetTools.const_defined?(:EntityConsoleDump)

    check_for_updates if GG_CabinetTools.respond_to?(:check_for_updates)
    UI.start_timer(0.5, false) do
      sync_user_config_from_server if GG_CabinetTools.respond_to?(:sync_user_config_from_server)
    end
    UI.start_timer(1.5, false) do
      GG_CabinetTools.maybe_show_promo_dialog if GG_CabinetTools.respond_to?(:maybe_show_promo_dialog)
    end

    file_loaded(__FILE__)
  end
end
