require 'time'

module IdeaReader
  class Market # rubocop:disable Metrics/ClassLength
    class IterationEndError < RuntimeError; end

    include Enumerable

    attr_accessor :browser
    attr_accessor :type

    def initialize(browser, type)
      @browser = browser
      @type = type
    end

    def each
      yield first
      loop do
        yield next_
      end
    rescue IterationEndError
      IdeaReader.logger.debug { 'each end' }
      self
    end

    def serial
      IdeaReader.logger.debug { 'serial' }
      @browser.driver.find_element(css: '.headArea_title > span.type > span.number.fR').text[/ : (.*)$/, 1].tap do |serial| # rubocop:disable Metrics/LineLength
        IdeaReader.logger.debug { "serial: #{serial}" }
      end
    end

    KEY = {
      '참여의견' => :cowork,
      '제보된 유사 아이디어' => :similar,
      '심사의견' => :opinion
    }

    def parse # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/LineLength
      data = {}

      # rubocop:disable Metrics/LineLength
      data[:type_a] =
        @browser.driver.find_element(css: '.headArea_title > span.type > em').attribute(:class)
      data[:type_b] =
        @browser.driver.find_element(css: '.headArea_title > span.type > span.by').text
      data[:type_c] =
        begin
          @browser.driver.find_element(css: '.nav > .nav_mini > span.info > span.emp').text
        rescue Selenium::WebDriver::Error::NoSuchElementError
          @type.capitalize
        end
      begin
        data[:d_day] =
          @browser.driver.find_element(css: '.nav > .nav_mini > span.info > span.empB').text[/^D - (\d+)$/, 1].to_i
      rescue Selenium::WebDriver::Error::NoSuchElementError # rubocop:disable Lint/HandleExceptions, Metrics/LineLength
      end
      data[:serial] = serial
      document_id = @browser.driver.find_element(css: 'em.favo').attribute(:id)[/^favoItem(\d+)$/, 1]
      data[:uri] = "http://mosaic.sec.samsung.net/kms/wagleLayout.do?method=link&type=idea.market&id=#{document_id}"
      data[:title] =
        @browser.driver.find_element(css: '.headArea_title > h2.title_Big > span').text
      data[:author] =
        @browser.driver.find_element(xpath: '//div[@class="contentArea"]/span/a[2]').attribute(:title)
      date, view_count, comment_count =
        @browser.driver.find_elements(xpath: '//div[@class="contentArea"]/span[not(@class)]').map(&:text)
      data[:c_at] = Time.parse(date).utc.strftime('%FT%T.%L%z')
      data[:u_at] = Time.now.utc.strftime('%FT%T.%L%z')
      data[:view_count] = (view_count || '')[/\d+$/].to_i
      data[:comment_count] = (comment_count || '')[/\d+$/].to_i
      @browser.driver.find_elements(css: 'ul.tabG > li').map(&:text).each do |kv|
        k, v = /^(.*)\((\d+)\)$/.match(kv).captures
        data[KEY[k]] = v.to_i if KEY.key?(k)
      end
      begin
        data[:coin] =
          @browser.driver.find_element(css: '.dataArea > .nav > .dataSet > .count > span.coin').text[/[\d,]+/].delete(',').to_i
      rescue Selenium::WebDriver::Error::NoSuchElementError # rubocop:disable Lint/HandleExceptions, Metrics/LineLength
      end
      begin
        data[:people] =
          @browser.driver.find_element(css: '.dataArea > .nav > .dataSet > .count > span.man').text.to_i
      rescue Selenium::WebDriver::Error::NoSuchElementError # rubocop:disable Lint/HandleExceptions, Metrics/LineLength
      end
      # rubocop:enable Metrics/LineLength
      IdeaReader.logger.debug { "data(parse): #{data}" }
      data
    end

    def title
      Selenium::WebDriver::Wait.new(timeout: 120).until do
        @browser.driver.find_element(css: 'li.title > span > a')
      end.text.tap { |title| IdeaReader.logger.debug { "title: #{title}" } } # rubocop:disable Style/MultilineBlockChain, Metrics/LineLength
    end

    def wait_for_changing_title
      prev = title
      yield
      Selenium::WebDriver::Wait.new(
        timeout: 120,
        ignore: [Selenium::WebDriver::Error::StaleElementReferenceError]
      )
        .until do
          prev != title
        end
    end

    def get # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
      IdeaReader.logger.debug { 'get' }
      @browser.driver.get(
        'http://mosaic.sec.samsung.net/kms/wagleLayout.do?method=view&menu=IDEA&subMenu=MARKET'
      )
      if @type == :concept
        IdeaReader.logger.debug { 'type is concept' }
        return
      end
      wait_for_changing_title do
        Selenium::WebDriver::Wait.new(timeout: 120).until do
          @browser.driver.find_element(
            xpath: "//div[@class='navigation_step4']/ul[@class='naviBar']/li/a[@id='#{@type.upcase}']" # rubocop:disable Metrics/LineLength
          )
        end.click
        IdeaReader.logger.debug { "menu clicked: #{@type}" }
      end
    end

    def first
      get
      Selenium::WebDriver::Wait.new(timeout: 120).until do
        @browser.driver.find_element(css: 'li.title > span > a')
      end.click
      IdeaReader.logger.debug { 'first idea clicked' }
      Selenium::WebDriver::Wait.new(timeout: 120).until do
        serial
      end
      IdeaReader.logger.debug { 'serial checked' }
      parse
    end

    def wait_for_changing_serial
      prev = serial
      yield
      Selenium::WebDriver::Wait.new(
        timeout: 120,
        ignore: [Selenium::WebDriver::Error::StaleElementReferenceError]
      )
        .until do
          prev != serial
        end
    end

    def next_
      wait_for_changing_serial do
        begin
          @browser.driver.find_element(xpath: '//a[text()="다음"]').click
        rescue Selenium::WebDriver::Error::NoSuchElementError
          raise IterationEndError
        end
        IdeaReader.logger.debug { 'next button clicked' }
      end
      parse
    end
  end
end
