module Veewee
  class Transaction

  def transaction(name,params, &block)
  end
  
  def transaction2(name,options= { :checksum => "nochecksum"}, &block)
     if snapshot_exists(@vmname,name+"-"+options[:checksum])
        load_snapshot_vmachine(@vmname,name+"-"+options[:checksum])
      else
        if snapshot_version_exists(@vmname,name)
          rollback_snapshot(@vmname,name)
          #rollback to snapshot prior to this one
        end
        yield
        create_snapshot_vmachine(@vmname,name+"-"+options[:checksum])
      end
    #end
  end

  def self.remove_snapshot_vmachine(vmname,snapname)
    Veewee::Shell.execute("VBoxManage snapshot '#{vmname}' delete '#{snapname}'")
  end

  def self.create_snapshot_vmachine(vmname,snapname)
    Veewee::Shell.execute("VBoxManage snapshot '#{vmname}' take '#{snapname}'")
  end

  def self.load_snapshot_vmachine(vmname,snapname)
    #if it running , shutdown first
    if (state_vmachine(vmname)=="running")
      stop_vmachine(vmname)
    end

    Veewee::Shell.execute("VBoxManage snapshot '#{vmname}' restore '#{snapname}'")
    #sometimes it takes some time to shutdown
    sleep 2
    Veewee::Shell.execute("VBoxManage startvm '#{vmname}'")
  end

  def self.snapshot_exists(vmname,snapname)
    list_snapshots(vmname).each { |name|
      if (name==snapname) then
        return true
      end
    }
    return false
  end

  def self.snapshot_version_exists(vmname,snapname)
        list_snapshots(vmname).each { |name|
          if name.match(/^#{snapname}-/) then
            return true
          end
        }
        return false
  end

  def self.rollback_snapshot(vmname,snapname)
    delete_flag=false

    savestate_recover=false
    if (state_vmachine(vmname)=="running")
      Veewee::Shell.execute("VBoxManage controlvm '#{vmname}' savestate")
      savestate_recover=true
     end

    list_snapshots(vmname).each { |name|
      if name.match(/^#{snapname}-/) then
        delete_flag=true
      end
      if (delete_flag) then
        remove_snapshot_vmachine(vmname,name)
      end
    }
    
    
     sleep 2

      Veewee::Shell.execute("VBoxManage startvm '#{vmname}'")

      if (savestate_recover)
        #Recovering from savestate nukes the network! This trick seem to work
        #Also within the vm /etc/init.d/networking restart , but that is OS specific
        #http://www.virtualbox.org/ticket/5666
        #http://www.virtualbox.org/ticket/5654
        #This is supposed to be fixed: http://www.virtualbox.org/changeset/25205 but alas
        Veewee::Shell.execute("VBoxManage controlvm '#{vmname}' nic1 nat")
        Veewee::Shell.execute("VBoxManage controlvm '#{vmname}' setlinkstate1 off")
        Veewee::Shell.execute("VBoxManage controlvm '#{vmname}' setlinkstate1 on")
        sleep 2

        #hmmm, virtualbox => when recovering from a restore , it looses the nat settings!!! So we need to do this again!!
        #thebox.ssh_enable_vmachine({:hostport => host_port , :guestport => 22} )
        #http://www.virtualbox.org/changeset/25402
        #[25402]: NAT: re-establish port-forwarding after savestate / restore state

      end

    end


    def self.list_snapshots(vmname)
      snapshotresult=Veewee::Shell.execute("VBoxManage showvminfo --machinereadable '#{vmname}' |grep ^SnapshotName| cut -d '=' -f 2").stdout
      snapshotlist=snapshotresult.gsub(/\"/,'').split(/\n/)
      return snapshotlist
    end

end
end