=begin
Copyright 2014, Andreas Eisenbarth
All Rights Reserved

Permission to use, copy, modify, and distribute this software for
any purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies.

THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

Name:         SceneNorthAngleTool.rb

Author:       Andreas Eisenbarth

Usage:        Menu 'View' → 'Toolbars' → 'North Angle Tool on Scenes'

Description:  This Plugin uses SketchUp's North Angle Tool to set the angle only
              to the currently selected scene.

Requires:     SketchUp Pro

Version:      1.0.0

Date:         23.01.2014
=end



module AE

class SceneNorthAngleTool

  PLUGIN_PATH = File.dirname(__FILE__) unless defined?(self::PLUGIN_PATH)

  def initialize
    @model = Sketchup.active_model
    # Save the previous value of shadow_info on the model
    @original = @model.shadow_info["NorthAngle"]
    Sketchup.send_action("selectNorthTool:")
    UI.start_timer(0.1, false) {
      north_tool_id = @model.tools.active_tool_id # NorthTool id
      # Set up a tools observer to check when the selectNorthTool is unselected
      @north_angle_tool_observer = NorthAngleToolObserver.new(self, north_tool_id)
      @model.tools.add_observer(@north_angle_tool_observer)
      # Set up a shadow_info observer to check whether the shadow_info["NorthAngle"] has changed
      @north_angle_observer = NorthAngleObserver.new(self)
      @model.shadow_info.add_observer(@north_angle_observer)
    }
  end

  def transfer_shadow_info
    if @model.method(:start_operation).arity == -1
      @model.start_operation("North Angle Tool on Scene", true, false, true)
    else
      @model.start_operation("North Angle Tool on Scene")
    end
    page = @model.pages.selected_page
    angle = @model.shadow_info["NorthAngle"]
    # Copy the value to the current scene
    page.use_shadow_info = true
    page.shadow_info["NorthAngle"] = angle
    @model.commit_operation
  end

  def cancel
    @model.shadow_info.remove_observer(@north_angle_observer)
    @model.tools.remove_observer(@north_angle_tool_observer)
    @model.shadow_info["NorthAngle"] = @original
    # TODO: Here the view resets and uses the NorthAngle from the model, not
    # from the scene (which should override it. Try one of these:
    # @model.pages.selected_page.update(4)
    # @model.active_view.invalidate
  end


  # Observer that watches shadowinfo changes done by the NorthAngleTool to the model.
  class NorthAngleObserver < Sketchup::ShadowInfoObserver

    def initialize(tool_instance)
      @tool_instance = tool_instance
    end

    def onShadowInfoChanged(shadow_info, type)
      if type == 4 # Solar orientation
         @tool_instance.transfer_shadow_info
      end
    end

  end


  # Observer that watches when the NorthAngleTool is unselected.
  class NorthAngleToolObserver < Sketchup::ToolsObserver

    def initialize(tool_instance, north_tool_id)
      @tool_instance = tool_instance
      @north_tool_id = north_tool_id
    end

    def onActiveToolChanged(tools, tool_name, tool_id)
      if tool_name != "NorthTool" && tool_id != @north_tool_id
        @tool_instance.cancel
      end
    end

  end


  unless file_loaded?( __FILE__ )
    toolbar = UI::Toolbar.new("North Angle Tool on Scenes")

    if Sketchup.is_pro?
      # Create Scene North Tool command.
      name = "Set North Tool on Scene"
      scene_north_tool_command = UI::Command.new(name){
        Sketchup.active_model.select_tool(SceneNorthAngleTool.new)
      }
      scene_north_tool_command.large_icon = File.join(PLUGIN_PATH, "images", "scene_north_tool_large.png")
      scene_north_tool_command.small_icon = File.join(PLUGIN_PATH, "images", "scene_north_tool_small.png")
      scene_north_tool_command.tooltip = ""
      toolbar.add_item(scene_north_tool_command)
    end

    # Create Scene North Text command.
    name = "Enter North Angle"
    prompt = "North Angle (0–360)"
    scene_north_text_command = UI::Command.new(name){
      shadow_info = Sketchup.active_model.pages.selected_page.shadow_info
      repeats = 0
      while repeats < 3
        begin
          input = UI.inputbox([prompt + " "], [shadow_info["NorthAngle"]], name)
          if (input != false)
            angle = input[0].to_f % 360.0
            shadow_info["NorthAngle"] = angle
          end
          repeats = 3
        rescue Exception => e
          $stderr.write("Scene North Angle Extension Error: #{e.class}: #{e.message}\n")
          UI.messagebox("Your input could not be understood. Please enter a number between 0 and 360.")
          repeats += 1
        end
      end
    }
    scene_north_text_command.large_icon = File.join(PLUGIN_PATH, "images", "scene_north_text_large.png")
    scene_north_text_command.small_icon = File.join(PLUGIN_PATH, "images", "scene_north_text_small.png")
    scene_north_text_command.tooltip = name
    toolbar.add_item(scene_north_text_command)

    # Show toolbar if it was open when we shutdown.
    toolbar.restore

    file_loaded( __FILE__ )
  end

end # class SceneNorthAngleTool

end # module AE
