# frozen_string_literal: true

# title: Export plugin example
# description: Speak the most recent entry (macOS)
# author: Brett Terpstra
# url: https://brettterpstra.com

# Example
#
# doing show -o sayit
#
# ## Configuration
#
# Change what the plugin says by generating a template with
# `doing template --type say`, saving it to a file, and
# putting the path to that file in `export_templates->say` in
# config.yml.
#
# export_templates:
#   say: /path/to/template.txt
#
# Use a different voice by adding a `say_voice` key to your
# config.yml. Use `say -v ?` to see available voices.
#
# say_voice: Zarvox

module Doing
  ##
  ## Plugin class
  ##
  class SayExport
    include Doing::Util

    #-------------------------------------------------------
    ## Plugin Settings. A plugin must have a self.settings
    ## method that returns a hash with plugin settings.
    ##
    ## trigger:   (required) Regular expression to match
    ## FORMAT when used with `--output FORMAT`. Registered
    ## name of plugin must be able to match the trigger, but
    ## alternatives can be included
    ##
    ## templates: (optional) Array of templates this plugin
    ## can export (plugin must have :template method)
    ##
    ##   Each template is a hash containing:
    ##               - name: display name for template
    ##               - trigger: regular expression for
    ##                 `template --type FORMAT`
    ##
    ##   If a template is included, a config key will
    ##   automatically be added for the user to override
    ##   The config key will be available at:
    ##
    ##       wwid.config['export_templates'][PLUGIN_NAME]
    ##
    ## config:    (optional) A Hash which will be
    ## added to the main configuration in the plugins section.
    ## Options defined here are included when config file is
    ## created or updated with `config --update`. Use this to
    ## add new configuration keys, not to override existing
    ## ones.
    ##
    ##   The configuration keys will be available at:
    ##
    ##      wwid.config['plugins'][PLUGIN_NAME][KEY]
    ##
    ## Method to return plugin settings (required)
    ##
    ## @return     Hash of settings for this plugin
    ##
    def self.settings
      {
        trigger: 'say(?:it)?',
        templates: [
          { name: 'say', trigger: 'say(?:it)?' }
        ],
        config: {
          'say_voice' => 'Fiona'
        }
      }
    end


    #-------------------------------------------------------
    ## Output a template. Only required if template(s) are
    ## included in settings. The method should return a
    ## string (not output it to the STDOUT).
    ##
    ## Method to return template (optional)
    ##
    ## @param      trigger  The trigger passed to the
    ##                      template function. When this
    ##                      method defines multiple
    ##                      templates, the trigger can be
    ##                      used to determine which one is
    ##                      output.
    ##
    ## @return     [String] template contents
    ##
    def self.template(trigger)
      return unless trigger =~ /^say(it)?$/

      'On %date, you were %title, recorded in section %section%took'
    end


    ##
    ## Render data received from an output
    ##             command
    ##
    ## @param      wwid       The wwid object with config
    ##                        and public methods
    ## @param      items      An array of items to be output
    ##                        { <Date>date, <String>title,
    ##                        <String>section, <Array>note }
    ## @param      variables  Additional variables including
    ##                        flags passed to command
    ##                        (variables[:options])
    ##
    ## @return     [String] Rendered output
    ##
    def self.render(wwid, items, variables: {})
      return if items.nil? || items.empty?

      # the :options key includes the flags passed to the
      # command that called the plugin use `puts
      # variables.inspect` to see properties and methods
      # when run
      opt = variables[:options]

      # This plugin just grabs the last item in the `items`
      # list (which could be the oldest or newest, depending
      # on the sort order of the command that called the
      # plugin). Most of the time you'll want to use :each
      # or :map to generate output.
      i = items[-1]

      # Format the item. Items are an object with 4 methods:
      # date, title, section (parent section), and note.
      # Start time is in item.date. The wwid object has some
      # methods for calculation and formatting, including
      # wwid.item.end_date to convert the @done timestamp to
      # an end date.
      if opt[:times]
        interval = i.interval

        if interval
          took = '. You finished on '
          finished_at = i.end_date
          took += finished_at.strftime('%A %B %e at %I:%M%p')

          d, h, m = wwid.format_time(interval)
          took += ' and it took'
          took += " #{d.to_i} days" if d.to_i.positive?
          took += " #{h.to_i} hours" if h.to_i.positive?
          took += " #{m.to_i} minutes" if m.to_i.positive?
        end
      end

      date = i.date.strftime('%A %B %e at %I:%M%p')
      title = i.title.gsub(/@/, 'hashtag ')
      tpl = template('say')

      if wwid.config['export_templates'].key?('say')
        cfg_tpl = wwid.config['export_templates']['say']
        tpl = cfg_tpl unless cfg_tpl.nil? || cfg_tpl.empty?
      end
      output = tpl.dup
      output.gsub!(/%date/, date)
      output.gsub!(/%title/, title)
      output.gsub!(/%section/, i.section)
      output.gsub!(/%took/, took || '')

      # Debugging output
      # warn "Saying: #{output}"

      # To provide results on the command line after the
      # command runs, use Doing.logger, which responds to
      # :debug, :info, :warn, and :error. e.g.:
      #
      # Doing.logger.info("This plugin has run")
      # Doing.logger.error("This message will be displayed even if run in --quiet mode.")
      #
      # Results are
      # provided on STDERR unless doing is run with
      # `--stdout` or non-interactively.
      Doing.logger.info('Spoke the last entry. Did you hear it?')

      # This export runs a command for fun, most plugins won't
      voice = wwid.config['plugins']['say']['say_voice'] || 'Alex'
      `say -v "#{voice}" "#{output}"`

      # Return the result (don't output to terminal with puts or print)
      output
    end

    # Register the plugin with doing.
    # Doing::Plugins.register 'NAME', TYPE, Class
    #
    # Name should be lowercase, no spaces
    #
    # TYPE is :import or :export
    #
    # Class is the plugin class (e.g. Doing::SayExport), or
    # self if called within the class
    Doing::Plugins.register 'say', :export, self
  end
end