# frozen_string_literal: true

# Copyright (c) 2008-2023 Minero Aoki, Kenshi Muto, Masayoshi Takahashi,
#                         KADO Masanori
#               2002-2007 Minero Aoki
#
# This program is free software.
# You can distribute or modify this program under the terms of
# the GNU LGPL, Lesser General Public License version 2.1.
#
require 'nkf'
require 'digest'

module ReVIEW
  module TextUtils
    def detab(str, ts = 8)
      add = 0
      len = nil
      str.gsub("\t") do
        len = ts - (($`.size + add) % ts)
        add += len - 1
        ' ' * len
      end
    end

    def split_paragraph(lines)
      pre = pre_paragraph
      post = post_paragraph
      trimmed_lines = trim_lines(lines)

      blocked_lines = [[]]
      trimmed_lines.each do |element|
        if element.empty?
          blocked_lines << [] if blocked_lines.last != []
        else
          blocked_lines.last << element
        end
      end

      blocked_lines.map! { |i| join_lines_to_paragraph(i) }

      if pre && post
        blocked_lines.map! { |i| pre + i + post }
      end

      blocked_lines
    end

    def add_space?(line1, line2, lang, lazy = nil)
      # https://drafts.csswg.org/css-text-3/#line-break-transform
      tail = line1[-1]
      head = line2[0]
      if tail.nil? || head.nil?
        return false
      end

      space = true
      # rule 2
      if %i[F W H].include?(Unicode::Eaw.property(tail)) &&
         %i[F W H].include?(Unicode::Eaw.property(head)) &&
         tail !~ /\p{Hangul}/ && head !~ /\p{Hangul}/
        space = nil
      end

      if %w[ja zh zh_CN zh_TW yi].include?(lang)
        # rule 3
        if (%i[F W H].include?(Unicode::Eaw.property(tail)) &&
            tail !~ /\p{Hangul}/ &&
            (head =~ /\p{P}/ || head =~ /\p{S}/ || Unicode::Eaw.property(head) == :A)) ||
           (%i[F W H].include?(Unicode::Eaw.property(head)) &&
            head !~ /\p{Hangul}/ &&
            (tail =~ /\p{P}/ || head =~ /\p{S}/ || Unicode::Eaw.property(tail) == :A))
          space = nil
        end

        # lazy than rule 3, but it looks better
        if lazy && ((%i[F W H].include?(Unicode::Eaw.property(tail)) &&
              tail !~ /\p{Hangul}/) ||
             (%i[F W H].include?(Unicode::Eaw.property(head)) &&
              head !~ /\p{Hangul}/))
          space = nil
        end
      end
      space
    end

    def join_lines_to_paragraph(lines)
      unless @book.config['join_lines_by_lang']
        return lines.join
      end

      lazy = true
      lang = 'ja'
      0.upto(lines.size - 2) do |n|
        if add_space?(lines[n], lines[n + 1], lang, lazy)
          lines[n] += ' '
        end
      end
      lines.join
    end

    private

    # remove elements at the back of `lines` if element is empty string
    # (`lines` should be Array of String.)
    #
    def trim_lines(lines)
      new_lines = lines.dup
      while new_lines[-1] && new_lines[-1].strip.empty?
        new_lines.pop
      end
      new_lines
    end
  end
end
