require 'win32ole'

module FenrirFSAPI_module
  def method_missing(cmd, *arg)
    begin
      @obj.invoke(cmd.to_s,*arg)
    rescue 
      raise 
    end
  end  
end

class FenrirFS_LG
  include FenrirFSAPI_module
  
  def initialize(group)
    @obj = group
  end
  attr_accessor :obj
  def name
    return obj.DisplayName
  end
  def each_label
    for no in [* 0..(@obj.LabelCount-1)]
      if @obj.Labels(no)!=nil then
        yield FenrirFS_L.new(@obj.Labels(no))
      end
    end
  end
end

class FenrirFS_L
  include FenrirFSAPI_module
  
  def initialize(l)
    @obj = l
  end
  attr_accessor :obj
  def name
    return obj.DisplayName
  end
  
  def changeLabel(newName=nil,newColor=nil,newGroup=nil)
    if(newName==nil) then
      newName=name
    end
    if(newColor==nil or newColor<0 or newColor>19 ) then
      newColor=obj.LabelColor
    end
    if(newGroup==nil) then
      newGroup=obj
    end
    if(newGroup.class==FenrirFS_LG) then
      newGroup=newGroup.obj
    elsif(newGroup.class==WIN32OLE and newGroup.ole_obj_help=="IFIFenrirFSLabelGroup") then
      # そのまま設定
    else
    end
    
    obj.ChangeLabel(newName,newColor,newGroup)
  end
end

class FenrirFS_LGList
  def initialize(groups=nil)
    @local_groupList=Hash.new
    if groups != nil then
      for obj in groups
          if FenrirFS_LG==obj.class then
            newObj = obj
          else
            newObj = FenrirFS_LG.new(obj)
          end
          @local_groupList[obj.DisplayName]=newObj
      end
    end
  end
  def size
    return @local_groupList.size
  end
  def [] (name)
    return @local_groupList[name]
  end
  def << (dat)
    newObj = dat
    if FenrirFS_LG.class!=dat then
      newObj = FenrirFS_LG.new(dat)
    end
    @local_groupList.store(dat.DisplayName,newObj)
  end
  
  def names 
    return @local_groupList.keys
  end
  
  def each
    @local_groupList.each_pair  { |key,value|
      yield key,value
    }
  end
  
  def each_value
    @local_groupList.each_value { |value|
      yield value
    }
  end
  
  def to_comArray
    ret = Array.new
    each_value { | value |
       ret.push(value.obj)
    }
    return ret
  end
  
  def each_name
    @local_groupList.each_key { |key|
      yield key
    }
  end
  
  def each_label_value
    @local_groupList.each_value { |value|
      for no in [* 0..(value.obj.LabelCount-1)]
        if value.obj.Labels(no)!=nil then
          yield FenrirFS_L.new(value.obj.Labels(no))
        end
      end
    }
  end
  def each_label_name
    @local_groupList.each_value { |value|
      for no in [* 0..(value.obj.LabelCount-1)]
        if value.obj.Labels(no)!=nil then
          yield value.obj.Labels(no).DisplayName
        end
      end
    }
  end
  
end

class FenrirFS_LList
  def initialize(group=nil)
    @local_labelList=Hash.new
#puts "FenrirFS_LList call!"
    if group.class == FenrirFS_LG or group.class == FenrirFS_L then
#puts "FenrirFS_LList call---1"
      self << group
    elsif group.class == FenrirFS_LGList then
#puts "FenrirFS_LList call---2"
      addList(group)
    end
  end
  
  def size
    return @local_labelList.size
  end
  
  def [] name
    return @local_labelList[name]
  end

  attr_accessor :local_labelList
  protected :local_labelList
  def add(value)
    ret = FenrirFS_LList.new()
    ret.local_labelList=(@local_labelList.merge(value.local_labelList))
    return ret
  end

  def match (pattern)
    newList =FenrirFS_LList.new
    @local_labelList.each_pair  { |key,value|
      if key.to_s.match(pattern) then
        newList<< value
      end
    }
    return newList
  end

  def add!(value)
    (@local_labelList.merge!(value.local_labelList))
    return self
  end

  def << (dat)
    if dat.class == FenrirFS_LG then
    
      for no in [* 0..(dat.obj.LabelCount-1)]
          newObj = dat.obj.Labels(no)
          if newObj.class==WIN32OLE and newObj.ole_obj_help.name=="IFIFenrirFSLabel"
#puts "#{newObj.DisplayName} -> #{no}"
              @local_labelList.store(newObj.DisplayName,FenrirFS_L.new(newObj))
          end
      end
    elsif dat.class == FenrirFS_L then
      @local_labelList.store(dat.name,dat)
    elsif dat.class==WIN32OLE and dat.ole_obj_help.name=="IFIFenrirFSLabel" then
      @local_labelList.store(dat.DisplayName,FenrirFS_L.new(dat))
    end
  end
  def addList (dat)
    if dat.class == FenrirFS_LGList then
      for name in [*dat.names]
        if dat[name].obj.IsDefaultGroup()!=false
          self << dat[name]
        end
      end
    end
  end
  def names 
    return @local_labelList.keys
  end
  def each
    @local_labelList.each_pair  { |key,value|
      yield key,value
    }
  end
  def each_value
    @local_labelList.each_value { |value|
      yield value
    }
  end
  def to_comArray
    ret = Array.new
    each_value { | value |
       ret.push(value.obj)
    }
    return ret
  end
  def each_name
    @local_labelList.each_key { |key|
      yield key
    }
  end
end

class FenrirFS_File
  include FenrirFSAPI_module
  def initialize(fenrirFile)
    if (fenrirFile.class==WIN32OLE and fenrirFile.ole_obj_help.name=="IFIFenrirFSFile") then
      @obj=fenrirFile
      @labels = Array.new
      refrashLables
    else
      raise ArgumentError,"IFIFenrirFSFileで無い！"
    end
  end
  attr_accessor :obj,:labels
  
  def refrashLables
    for l in [* 0..@obj.LabelCount-1] do
      @labels << @obj.Labels(l)
    end
  end
  
  def name
    return @obj.DisplayFileName.to_s
  end

  def fullPath
    return @obj.FullPath.to_s
  end
  
  def localPath(topPathDeleteSize=0)
    require 'Pathname'
    require 'FileUtils'
#    ss=@obj.FullPath.to_s.split("/")
    fileName  = Pathname.new(@obj.FullPath.to_s)
    if(topPathDeleteSize==-1) then
      if((makepath=fileName.parent.to_s.match(/^[a-zA-Z]\:(.*)/))!=nil)
         makepath
         return makepath[1]
      end
      return fileName.parent.to_s
    elsif (topPathDeleteSize>0) then
      makepath=fileName.parent.to_s
      return makepath[topPathDeleteSize,makepath.size]
    else
      return fileName.parent.to_s
    end
  end
  def moveTo(basePath,topPathDeleteSize=-1)
    if (topPathDeleteSize==0)
       raise ArgumentError "topPathDeleteSizeは0以外を指定してください"
    end
    oldPath=localPath() + '\\' + @obj.DisplayFileName
    newPath=basePath.to_s + localPath(topPathDeleteSize)
#    puts oldPath
#    puts newPath
    if File.exist?(newPath)==false then
       FileUtils.mkpath(newPath)
    end
    newPath += "\\" + @obj.DisplayFileName
    moveOk=true
    if(block_given? == true) then 
      moveOk = yield oldPath,newPath
    end
    if File.exist?(oldPath)==true and File.exist?(newPath)==false and moveOk==true then
      FileUtils::mv( oldPath, newPath)
      return true
    end
    return false
  end
end

class FenrirFS_Files < Array
  def << inst
    if FenrirFS_File==inst.class
      super
    elsif inst.class==WIN32OLE and inst.ole_obj_help.name=="IFIFenrirFSFile" then
      super(FenrirFS_File.new(inst))
    else
      raise ArgumentError,"FenrirFS_Fileで無い！"
    end
  end
  def push inst
    if FenrirFS_File==inst.class
      super
    elsif inst.class==WIN32OLE and inst.ole_obj_help.name=="IFIFenrirFSFile" then
      super(FenrirFS_File.new(inst))
    else
      raise ArgumentError,"FenrirFS_Fileで無い！"
    end
  end
  
  def each_fsfile_and_lable
    self.each { | file |
      yield file.obj,file.labels
    }
  end

  def each_fsfile_and_lable_ex
    self.each { | file |
      yield file,file.labels
    }
  end
  
  def display
    self.each { | file |
      puts "#{file.obj.DisplayFileName} , #{file.obj.FullPath} , FileId=#{file.obj.FileId} , ?Alias=#{file.obj.Alias}"
    }
  end
end

class FenrirFS_Qurys < Array
end

class FenrirFSApp
   require 'win32ole'

   @@FenrirFS = WIN32OLE.new('FenrirFS_API.FIFenrirFSAPI')
   
   def self.getLabelGroups(profileName)
      labelGroupList=FenrirFS_LGList.new
      fenrirProfile = makeProfile(profileName)
      for no in [* 0..(fenrirProfile.LabelGroupList.GroupCount.to_i-1)] do
        labelGroupList << fenrirProfile.LabelGroupList.LabelGroup(no)
      end
      return labelGroupList
   end
   
   def self.getLabelGroup(profileName,name=nil)
      __labelGroup=nil
      fenrirProfile = makeProfile(profileName)
      if name==nil then
        __labelGroup=FenrirFS_LG.new(fenrirProfile.LabelGroupList.DefaultGroup)
      else
        for no in [* 0..(fenrirProfile.LabelGroupList.GroupCount.to_i-1)] do
      	  if name==fenrirProfile.LabelGroupList.LabelGroup(no).DisplayName then
        	  __labelGroup = FenrirFS_LG.new(fenrirProfile.LabelGroupList.LabelGroup(no))
        	  break
          end
        end
      end
      return __labelGroup
   end
   
   def self.getLabelMenbers(lists,name = nil)
   
      if (lists.class==String) then
        lists=makeProfile(lists)
      end
      if (FenrirFS_LGList==lists.class) then
        if( name==nil ) then
          ret = FenrirFS_LList.new(lists)
        else
          ret = FenrirFS_LList.new(lists[name])
        end
        return ret
      elsif (lists.class==WIN32OLE and lists.ole_obj_help.name=="IFIFenrirFSProfile") then
        ret = FenrirFS_LList.new
        for no in [* 0..(lists.LabelGroupList.LabelCount.to_i-1)] do
          ret << lists.LabelGroupList.Labels(no)
        end
        return ret
      end
      return nil
   end
   
   def self.findLabel(proFile,name)
      if (proFile.class==String) then
        proFile=makeProfile(proFile)
      end
      
      item = proFile.LabelGroupList.FindLabelByName(name)
      if(item==nil) then
        return nil
      end
      return FenrirFS_L.new(item)
   end
   
   def self.findLabelGroup(proFile,name)
      if (proFile.class==String) then
        proFile=makeProfile(proFile)
      end
      
      item = proFile.LabelGroupList.FindGroupByName(name)
      if(item==nil) then
        return nil
      end
      return FenrirFS_LG.new(item)
   end
   
   def self.getFiles(profile,lists)
   
      if (FenrirFS_LList==lists.class) then
        fenrirProfile = makeProfile(profile)
        ret = FenrirFS_Files.new()
        lists.each_value { |value|
          fenrirProfile.FileList.ClearFileCategories()
          fenrirProfile.FileList.AddFileCategory(value.obj)
          fenrirProfile.FileList.UpdateFileList(0)
          for i in [* 0..fenrirProfile.FileList.Count-1] do
            ret << fenrirProfile.FileList.Files(i)
          end
        }
        return ret
      elsif (FenrirFS_L==lists.class) then
        fenrirProfile = makeProfile(profile)
        ret = FenrirFS_Files.new()
        fenrirProfile.FileList.ClearFileCategories()
        fenrirProfile.FileList.AddFileCategory(lists.obj)
        fenrirProfile.FileList.UpdateFileList(0)
        for i in [* 0..fenrirProfile.FileList.Count-1] do
          ret << fenrirProfile.FileList.Files(i)
        end
        return ret
      elsif (FenrirFS_LG==lists.class) then
        fenrirProfile = makeProfile(profile)
        ret = FenrirFS_Files.new()
        lists.each_label { |value|
        puts value.obj
          fenrirProfile.FileList.ClearFileCategories()
          fenrirProfile.FileList.AddFileCategory(value.obj)
          fenrirProfile.FileList.UpdateFileList(0)
          for i in [* 0..fenrirProfile.FileList.Count-1] do
            ret << fenrirProfile.FileList.Files(i)
          end
        }
        return ret
      end
      return nil
   end
   
   
   def self.getStarFiles(profile)
        fenrirProfile = makeProfile(profile)
        ret = FenrirFS_Files.new()
        fenrirProfile.FileList.ClearFileCategories()
        fenrirProfile.FileList.AddFileCategory(fenrirProfile.FolderList.StarFolder)
        fenrirProfile.FileList.UpdateFileList(0)
        for i in [* 0..fenrirProfile.FileList.Count-1] do
          ret << fenrirProfile.FileList.Files(i)
        end
        return ret
   end
   def self.makeProfile(profileName)
      fenrirProfile = @@FenrirFS.CreateProfile(profileName)
      return fenrirProfile
   end
   
   def self.setLabelToFile(profile,file,label,archive=true)
      if (profile.class==String) then
        profile=makeProfile(profile)
      end
      if (label.class==String) then
        label=findLabel(profile,label)
      end
      if (label.class==FenrirFS_L) then
        label=label.obj
      end
      if (file.class==FenrirFS_File) then
        file=file.obj
      end
      profile.SetLabelToFile(label,file,archive)
   end
   
end

#puts FenrirFSApp.findLabel('all','変換候補').name

#puts FenrirFSApp.findLabel('all','pacopaco').GetFileCount()

#files = FenrirFSApp.getStarFiles('all')
#files.display
