# Displays desktop message boxes
class Desktop_Message
  HORIZ_MARGIN = 8
  VERT_MARGIN = 8

  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
    @sprite_messagebox = Sprite.new(@viewport)
    @sprite_messagebox.bitmap = RPG::Cache.picture('cg_desktop_messagebox')
    @sprite_messagebox.zoom_x = @sprite_messagebox.zoom_y = 2
    @sprite_messagebox.x = (Graphics.width) / 2 - 320
    @sprite_messagebox.y = (Graphics.height) / 2 - 240
    @sprite_messagebox.shader = Shader::CRT
    @sprite_text = Sprite.new(@viewport)
    @contents = Bitmap.new(Graphics.width, Graphics.height)
    Language.register_text_sprite(self.class.name + "_contents", @contents)
    @sprite_text.bitmap = @contents
    @sprite_text.y = (Graphics.height - Graphics.height) / 2
    @sprite_messagebox.z = 1
    @sprite_text.z = 2
    @sprite_text.zoom_x = @sprite_text.zoom_y = 1
    @viewport.z = 9999
    @viewport.visible = false

    @sprite_messagebox.opacity = 0
    @sprite_text.opacity = 0

    # Animation flags
    @fade_in = false
    @fade_out = false
  end
  #--------------------------------------------------------------------------
  # * Dispose
  #--------------------------------------------------------------------------
  def dispose
    terminate_message
    $game_temp.message_window_showing = false
    @contents.dispose
    #@sprite_messagebox.dispose
    @sprite_text.dispose
    @viewport.dispose
  end
  #--------------------------------------------------------------------------
  # * Terminate Message
  #--------------------------------------------------------------------------
  def terminate_message
    # Call message callback
    if !@skip_message_proc && $game_temp.message_proc != nil
      $game_temp.message_proc.call
      $game_temp.message_proc = nil
    end
    $game_temp.message_desktop_text = nil
  end
  #--------------------------------------------------------------------------
  # * Refresh: Load new message text and pre-process it
  #--------------------------------------------------------------------------
  def refresh
    # Initialize
    text = ''
    y = -1
    widths = []

    # Pre-process text
    text_raw = $game_temp.message_desktop_text.to_str

    # Substitute variables, actors, player name, newlines, etc
    text_raw.gsub!(/\\v\[([0-9]+)\]/) do
      $game_variables[$1.to_i]
    end
    text_raw.gsub!(/\\n\[([0-9]+)\]/) do
      $game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
    end
    text_raw.gsub!("\\p", $game_oneshot.player_name)
    text_raw.gsub!("\\n", "\n")
    # Handle text-rendering escape sequences
    text_raw.gsub!(/\\c\[([0-9]+)\]/, "\000[\\1]")
    # Finally convert the backslash back
    text_raw.gsub!("\\\\", "\\")

    # Now split text into lines by measuring text metrics
    x = y = 0
    maxwidth = @contents.width - HORIZ_MARGIN * 2
    spacesize = @contents.text_size(' ')
    for i in text_raw.split(/ /)
      # Split each word around newlines
      newline = false
      for j in i.split("\n")
        # Handle newline
        if newline
          text << "\n"
          widths << x
          x = 0
          y += 1
        else
          newline = true
        end

        # Get width of this word and see if it goes out of bounds
        width = @contents.text_size(j.gsub(/\000\[[0-9]+\]/, '')).width
        if x + width > maxwidth
          text << "\n"
          x = 0
          y += 1
        end

        # Append word to list
        if x == 0
          text << j
        else
          text << ' ' << j
        end
        x += width + spacesize.width
      end
    end
    widths << x if y < 4

    # Prepare renderer
    @contents.clear
    @contents.font.color = Color.new(44, 37, 54, 255)
    y_top = (Graphics.height - widths.length * 24) / 2
    x = (Graphics.width - widths[0]) / 2
    y = 0

    # Get 1 text character in c (loop until unable to get text)
    while ((c = text.slice!(/./m)) != nil)
      # \n
      if c == "\n"
        y += 1
        x = (Graphics.width - widths[y]) / 2
        next
      end
      # \c[n]
      if c == "\000"
        # Change text color
        text.sub!(/\[([0-9]+)\]/, "")
        color = $1.to_i
        if color >= 0 and color <= 7
          @contents.font.color = Window_Base.text_color(color)
        end
        # go to next text
        next
      end
      # Draw text
      @contents.draw_text(x+2, y_top + y * 24, 40, 24, c)
      # Add x to drawn text width
      x += @contents.text_size(c).width
    end
    Graphics.frame_reset
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Handle fade-out effect
    if @fade_out
      @sprite_text.opacity -= 200
      @sprite_messagebox.opacity -= 200
      if @sprite_text.opacity <= 0
        @sprite_messagebox.opacity = 0
        @fade_out = false
        @viewport.visible = false
        $game_temp.message_window_showing = false
      end
      return
    end

    # Handle fade-in effect
    if @fade_in
      @sprite_text.opacity += 200
      @sprite_messagebox.opacity += 200
      if @sprite_text.opacity >= 255
      @sprite_messagebox.opacity = 255
        @fade_in = false
        $game_temp.message_window_showing = true
      end
      return
    end

    if visible
      if Input.trigger?(Input::ACTION) || Input.trigger?(Input::CANCEL) || (Input.press?(Input::R) && $game_switches[253])
        terminate_message
        @fade_out = true
      end
    end

    # Message is over and should be hidden or advanced to next
    if $game_temp.message_desktop_text == nil
      @fade_out = true if @viewport.visible
    else
      if !@viewport.visible
        # Fade in
        refresh
        @viewport.visible = true
        @fade_in = true
        Audio.se_play("Audio/SE/pc_messagebox.wav", (Audio.sfx_volume * 0.9).to_i, 150)
      end
    end

  end
  #--------------------------------------------------------------------------
  # * Variables
  #--------------------------------------------------------------------------
  def visible
    @viewport.visible
  end
  def visible=(val)
    @viewport.visible = val
  end
end
