# encoding: utf-8
=begin

 * Name: SiSU

 * Description: a framework for document structuring, publishing and search

 * Author: Ralph Amissah

 * Copyright: (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
   2007, 2008, 2009, 2010, 2011, 2012, 2013 Ralph Amissah, All Rights Reserved.

 * License: GPL 3 or later:

   SiSU, a framework for document structuring, publishing and search

   Copyright (C) Ralph Amissah

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   Software Foundation, either version 3 of the License, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
   more details.

   You should have received a copy of the GNU General Public License along with
   this program. If not, see <http://www.gnu.org/licenses/>.

   If you have Internet connection, the latest version of the GPL should be
   available at these locations:
   <http://www.fsf.org/licensing/licenses/gpl.html>
   <http://www.gnu.org/licenses/gpl.html>

   <http://www.sisudoc.org/sisu/en/manifest/gpl.fsf.html>

 * SiSU uses:
   * Standard SiSU markup syntax,
   * Standard SiSU meta-markup syntax, and the
   * Standard SiSU object citation numbering and system

 * Hompages:
   <http://www.jus.uio.no/sisu>
   <http://www.sisudoc.org>

 * Download:
   <http://www.sisudoc.org/sisu/en/SiSU/download.html>

 * Git
   <http://sources.sisudoc.org/gitweb/?p=code/sisu.git;a=summary>
   <http://sources.sisudoc.org/?p=code/sisu.git;a=blob;f=lib/sisu/v3/shared_sisupod_source.rb;hb=HEAD>

 * Ralph Amissah
   <ralph@amissah.com>
   <ralph.amissah@gmail.com>

 ** Description: create sisupod filetype and copy it to output directory!

=end
module SiSU_Source
  include SiSU_Env
  class SiSUpodSource
    require_relative 'sysenv'                           # sysenv.rb
    require_relative 'particulars'                      # particulars.rb
    def initialize(opt,build=nil,place=nil)
      @opt=opt
      m=/.+\/(?:src\/)?(\S+)/im
      @date=SiSU_Env::InfoDate.new.dt
      @env=SiSU_Env::InfoEnv.new(@opt.fns)
      @ver=SiSU_Env::InfoVersion.instance.get_version
      @v=(@opt.cmd =~/[VM]/) ? 'v' : ''
      @particulars=SiSU_Particulars::CombinedSingleton.instance.get_all(opt)
      @file=@particulars.file
      @local_path="#{@file.output_path.sisupod.dir}"
      processing_sisupod=@env.processing_path.processing_sisupod(@opt)
      processing_sisupod.make
      path_pod=processing_sisupod.paths[:sisupod]
      path_pod_fnb=processing_sisupod.paths[:fnb]
      FileUtils::mkdir_p(path_pod) unless FileTest.directory?(path_pod)
      @path_pod={
        fnb:       path_pod_fnb,
        pod:       path_pod,
        doc:       path_pod + '/' + Gt[:doc] + '/' + @opt.lng,
        po:        path_pod + '/' + Gt[:po] + '/' + @opt.lng,
        pot:       path_pod + '/' + Gt[:pot],
        conf:      path_pod + '/' + Gt[:conf],
        skin:      path_pod + '/' + Gt[:skin],
        image:     path_pod + '/' + Gt[:image],
        audio:     path_pod + '/' + Gt[:audio],
        video:     path_pod + '/' + Gt[:video],
      }
    end
    def read
      unless @opt.cmd =~/q/
        @opt.cmd=~/[MVv]/ \
        ? SiSU_Screen::Ansi.new(@opt.cmd,'Assemble SiSU source',"[#{@opt.f_pth[:lng_is]}] #{@opt.fno}").green_hi_blue
        : ''
      end
      unless @opt.fns.empty?
        directories
        pod_source_build #this needs to be built in case of multi-lingual for all of them, before single pass tar
      end
    end
    def directories
      SiSU_Env::InfoEnv.new.sisupod_v3(@opt)
    end
    def select_skin(skin='')                                                   #skin loading logic here
      load "#{SiSU_lib}/defaults.rb"
      @skin={}
      skin_path = [
        "#{@opt.base_path}/_sisu/skin",
        "#{@env.path.home}/.sisu/skin",
        '/etc/sisu/skin',
        "#{@path_pod[:pod]}/external_document/skin" #CHECK
      ]
      sk_doc,sk_dir="#{Gt[:doc]}/#{skin}.rb","dir/skin_#{@env.stub_pwd}.rb"
      skin_path.each do |v|                                                    #document skin priority 1
        if FileTest.file?("#{v}/#{sk_doc}")
          @skin={ name_path: "#{v}/#{sk_doc}", type: :doc }
          break
        end
      end
      unless @skin.length > 0
        skin_path.each do |v|                                                  #directory skin priority 2
          if FileTest.file?("#{v}/#{sk_dir}")
            @skin={ name_path: "#{v}/#{sk_dir}", type: :dir }
            break
          end
        end
      end
      @skin
    end
    def images_extract(f,images)                                                # consider using param info
      rgx_image=/(?:^|[^_\\])\{(?:\s*|\~\^\s+)(\S+?\.(?:png|jpg|gif)\b)/m
      if f !~/^%+\s/ \
      and f =~rgx_image
        images << f.scan(rgx_image).uniq
      end
      images.flatten
    end
    def pod_source_build
      @pwd=Dir.pwd
      @rgx_rb_image=/["']\S*?([a-zA-Z0-9_-]+?\.(?:png|jpg|gif))["']/
      @rgx_image=/(?:^|[^_\\])\{\s*(\S+?\.(?:png|jpg|gif))/
      @rgx_skin=/^\s+:skin:\s+(\S+)/
      @rgx_doc_import=/^<<\s*(\S+?\.ss[ti])/
      file_array=IO.readlines(@opt.fno,'')
      skin,images,doc_import=[],[],[]
      doc_import_dir=@opt.sub_location
      file_array.each do |f|                                                   #% work area
        if f !~/^%+\s/
          skin << f.scan(@rgx_skin).uniq.flatten if f =~@rgx_skin
          f=f.gsub(/<:=(\S+?)>/,'{ c_\1.png 14x14 }image')                                                           # embedded symbol (image)
          if f !~/^%+\s/ \
          and f =~@rgx_image
            images=images_extract(f,images)
          end
          if @opt.fno =~/\.ssm$/
            doc_import << f.scan(@rgx_doc_import) if f =~@rgx_doc_import
          end
        end
      end
      if doc_import.length > 0
        doc_import=doc_import.uniq.flatten
        doc_import.each do |fn|
          file_array=IO.readlines(fn,'')
          file_array.each do |f|                                                   #% work area
            if f !~/^%+\s/ \
            and f =~@rgx_image
              images=images_extract(f,images)
            end
          end
        end
      end
      docskin=nil
      if skin \
      and skin.length > 0
        docskin=skin.pop.flatten.join
        skin_source=select_skin(docskin)
      else
        skin_source=select_skin
      end
      docskin_place="#{@path_pod[:skin]}/#{skin_source[:type].to_s}"
      FileUtils::mkdir_p(docskin_place)
      if skin_source[:type] == :dir
        docskin_with_path="#{docskin_place}/skin_#{@env.stub_pwd}.rb"
        docskin=[docskin_with_path.gsub(/.+?\/(skin_\S+?)\.rb/,'\1')]
        docskin='skin_sisupod'
      end
      if skin_source \
      and skin_source[:name_path]
        unless skin_source[:name_path].nil? \
        or skin_source[:name_path].empty?
          if FileTest.file?(skin_source[:name_path])
            FileUtils::cp(skin_source[:name_path],"#{docskin_place}/#{docskin}.rb")
            skinfile_array=IO.readlines(skin_source[:name_path],'')
            para_images=[]
            skinfile_array.each do |f|                                           #% work area
              unless f =~/^%+ / #hmmm
                images << f.scan(@rgx_rb_image).uniq if f =~@rgx_rb_image
                #does not really discriminate, may duplicate images in sisu file, and may take images from default image pool
              end
            end
          else STDERR.puts %{\t*WARN* did not find - "#{skin_source[:name_path]}" [#{__FILE__}:#{__LINE__}]}
          end
        end
      end
      #1. mapping in doc dir?
      #2. need images used by skin, scan skin??
      if images \
      and images.length > 1
        images=images.flatten.uniq
        images.delete_if {|x| x =~/https?:\/\// }
        #images=images.sort
        FileUtils::mkdir_p(@path_pod[:image])
        #unattractive hard coding ... !
        image_path='_sisu/image'
        images_pwd="#{@opt.base_path}/#{image_path}"
        ##sequence copies base images, defaults used in all html outputs
          #image_source_base='/usr/share/sisu/image'
          #dir_pwd=Dir.pwd
          #Dir.chdir(image_source_base)
          #base_images=Dir.glob('*')
          #base_images.each do |i|
          #  FileUtils::cp_r(i,"#{images_path_pod}/#{i}")
          #end
          #Dir.chdir(dir_pwd)
        if FileTest.directory?(images_pwd)
          images=images.uniq
          images.each do |i|
            if FileTest.file?("#{images_pwd}/#{i}")
              FileUtils::cp("#{images_pwd}/#{i}","#{@path_pod[:image]}/#{i}") if FileTest.file?("#{images_pwd}/#{i}")
            else STDERR.puts %{\t*WARN* did not find image - "#{images_pwd}/#{i}" [#{__FILE__}:#{__LINE__}]}
            end
          end
        else STDERR.puts %{\t*WARN* did not find - #{images_pwd} #{@path_pod[:image]} [#{__FILE__}:#{__LINE__}]}
        end
      end
      if doc_import.length > 0 \
      and @opt.fno =~/\.ssm$/
        doc_import.each do |f|
          if FileTest.file?("#{@opt.base_path}#{doc_import_dir}/#{f}")
            FileUtils::cp("#{@opt.base_path}#{doc_import_dir}/#{f}","#{@path_pod[:doc]}/#{f}")
          else STDERR.puts %{\t*WARN* did not find image - "#{@opt.base_path}#{doc_import_dir}/#{f}" [#{__FILE__}:#{__LINE__}]}
          end
        end
      end
      x=@env.document_language_versions_found                                  #check multiple document language versions (param not used)
      if x[:f] \
      and x[:f].length > 0                                                     #store multiple document language versions, sisupod
        x[:f].each do |f|
          FileUtils::mkdir_p(@path_pod[:doc]) unless FileTest.directory?(@path_pod[:doc])
          if f[:f] =~/\~(\S{2,3})\.ss[tm]$/
            lng_f=$1
            if @opt.lng == lng_f
              if @opt.fno =~/\.ssm$/
                if FileTest.file?("#{@opt.base_path}#{doc_import_dir}/#{f[:f]}")
                  FileUtils::cp("#{@opt.base_path}#{doc_import_dir}/#{f[:f]}",
                    "#{@path_pod[:doc]}/#{f[:n]}")
                else STDERR.puts %{\t*WARN* did not find - "#{@opt.base_path}#{doc_import_dir}/#{f[:f]}" [#{__FILE__}:#{__LINE__}]}
                end
              else
                if FileTest.file?("#{@opt.base_path}/#{f[:f]}")
                  cpy= :no
                  cpy=if f[:f] =~ /^#{@opt.f_pth[:lng_is]}\// \
                  or f[:f] =~ /~#{@opt.f_pth[:lng_is]}\.sst/
                    p "#{@opt.base_path}/#{f[:f]} --> #{@path_pod[:doc]}/#{f[:n]}"
                    :yes
                  elsif f[:f] !~ /^(?:#{Px[:lng_lst_rgx]})\/|~(?:#{Px[:lng_lst_rgx]})\.sst/ \
                  and @opt.f_pth[:lng_is] == 'en'
                    p "#{@opt.base_path}/#{f[:f]} --> #{@path_pod[:doc]}/#{f[:n]}"
                    :yes
                  else :no
                  end
                  if cpy == :yes
                    FileUtils::cp("#{@opt.base_path}/#{f[:f]}",
                      "#{@path_pod[:doc]}/#{f[:n]}")
                  end
                else STDERR.puts %{\t*WARN* did not find - "#{@opt.base_path}/#{f[:f]}" [#{__FILE__}:#{__LINE__}]}
                end
              end
            end
          else
            if @opt.fno =~/\.ssm$/
              if FileTest.file?("#{@opt.base_path}#{doc_import_dir}/#{f[:f]}")
                FileUtils::cp_r("#{@opt.base_path}#{doc_import_dir}/#{f[:f]}",
                  "#{@path_pod[:doc]}/#{f[:n]}")
              else STDERR.puts %{\t*WARN* did not find - "#{@opt.base_path}#{doc_import_dir}/#{f[:f]}" [#{__FILE__}:#{__LINE__}]}
              end
            else
              if FileTest.file?("#{@opt.base_path}/#{f[:f]}")
                cpy= :no
                cpy=if f[:f] =~ /^#{@opt.f_pth[:lng_is]}\// \
                or f[:f] =~ /~#{@opt.f_pth[:lng_is]}\.sst/
                  p "#{@opt.base_path}/#{f[:f]} --> #{@path_pod[:doc]}/#{f[:n]}"
                  :yes
                elsif f[:f] !~ /^(?:#{Px[:lng_lst_rgx]})\/|~(?:#{Px[:lng_lst_rgx]})\.sst/ \
                and @opt.f_pth[:lng_is] == 'en'
                  p "#{@opt.base_path}/#{f[:f]} --> #{@path_pod[:doc]}/#{f[:n]}"
                  :yes
                else :no
                end
                if cpy == :yes
                  FileUtils::cp("#{@opt.base_path}/#{f[:f]}",
                    "#{@path_pod[:doc]}/#{f[:n]}")
                end
              else STDERR.puts %{\t*WARN* did not find - "#{@opt.base_path}/#{f[:f]}" [#{__FILE__}:#{__LINE__}]}
              end
            end
          end
        end
      end #NB not all possibilies met, revisit, also in case of composite file may wish to add README
    end
  end
end
__END__
question?:                   should you permit the packing of multiple documents in single .xz ?

  open @opt.fns, parse file
    extract from file content:
      images and copy each image from whatever image source to _sisu/sisupod/sisu/_sisu/image
      skin and copy active skin from whatever source to _sisu/sisupod/sisu/_sisu/skin/doc
      extract from skin images required by skin

   remove previously existing contents of _/sisu/sisupod &
   make directory structure:

v3 -->
   _sisu
     sisupod
       doc
         manifest.txt
         en/content.sst                [file content]
         fr/content.sst
         _sisu
           conf
             skin/
               doc                     [relevant skin if any other than default]
           image (ln -s ../../image)
           audio (ln -s ../../audio)
           video (ln -s ../../video)
       image                           [all images for specific document gathered here]
       audio
       video

v2 -->
   _sisu
     sisupod
       content.sst                     [file content]
       filename.sst                    [link to content.sst]
       _sisu/
         skin/
           doc                         [relevant skin if any other than default]
         image/                        [all images for specific document gathered here]

sisu
  _sisu
    sisurc.yml
    skin/
      dir/
      doc/
      misc/
      site/
      yaml/
    convert/
    standard_terms/
    image
    processing
      dal/
      tex/
      texinfo/
      tune/
    sisupod

special case

composite file (master), e.g.
SiSU.ssm
