#!/usr/bin/env ruby -w

require 'net/http'

# WoWhead URL Format http://www.wowhead.com/?object=xxxxx
# Data is embeded as arry of arrays within a javascript call
# return mp_Embed('Searing Gorge',[[56,76.6],[64.6,49.1],[66.2,37.7],[68,75.1]],this)
module LuaRuby
  def ruby_to_lua(v)
    if v=~ /\D+/
      return "\"#{v}\""
    else
      return v
    end
  end
end
# Add to_lua method to hash and array
class Array
  include LuaRuby
  def to_lua(depth=1)
    result = "{"
    each {|v|
        if v.instance_of? Array
          result << v.to_lua(depth+1)
        elsif v.instance_of? Hash
          result << v.to_lua(depth+1)
        else
          myval = ruby_to_lua(v)
          result << "\"#{myval}\","
        end
      }
    result << "}\n"
    return result
  end
end
class Hash
  include LuaRuby
  def to_lua(depth=1)
    # code here to generate lua out
    result = ("\t" * depth) +"{\n"
    keys.each {|k|
      mykey = ruby_to_lua(k)
      myval = fetch(k)
      if myval.instance_of? Hash
        result << ("\t" * depth) + "[#{mykey}] = \n" + myval.to_lua(depth+1)
      elsif myval.instance_of? Array
        result << ("\t" * depth) + "[#{mykey}] = \n" + myval.to_lua(depth+1)
      else
        myval = ruby_to_lua(myval)
        result << ("\t" * depth)+ "[#{mykey}] = #{myval},\n"
      end
      }
    comma = ""
    if depth > 1
      comma = ","
    end
    return result << ("\t" * depth) + "}#{comma}\n"
  end
end
minerals = Hash.new
herbs = Hash.new
gases = Hash.new
treasure = Hash.new
#
#
zone_map = {
  "Arathi Highlands" => 1,
	"Orgrimmar" => 2,
	"Eastern Kingdoms" => 3,
	"Undercity" => 4,
	"The Barrens" => 5,
	"Darnassus" => 6,
	"Azuremyst Isle" => 7,
	"Un'Goro Crater" => 8,
	"Burning Steppes" => 9,
	"Wetlands" => 10,
	"Winterspring" => 11,
	"Dustwallow Marsh" => 12,
	"Darkshore" => 13,
	"Loch Modan" => 14,
	"Blade's Edge Mountains" => 15,
	"Durotar" => 16,
	"Silithus" => 17,
	"Shattrath City" => 18,
	"Ashenvale" => 19,
	"Azeroth" => 20,
	"Nagrand" => 21,
	"Terokkar Forest" =>22,
	"Eversong Woods" =>23,
	"Silvermoon City" => 24,
	"Tanaris" => 25,
	"Stormwind City" => 26,
	"Swamp of Sorrows" => 27,
  "Eastern Plaguelands" => 28,
	"Blasted Lands" => 29,
	"Elwynn Forest" => 30,
	"Deadwind Pass" => 31,
	"Dun Morogh" => 32,
	"The Exodar" => 33,
	"Felwood" => 34,
	"Silverpine Forest" => 35,
	"Thunder Bluff" => 36,
	"The Hinterlands" => 37,
	"Stonetalon Mountains" => 38,
	"Mulgore" => 39,
	"Hellfire Peninsula" => 40,
	"Ironforge" => 41,
	"Thousand Needles" => 42,
	"Stranglethorn Vale" => 43,
	"Badlands" => 44,
	"Teldrassil" => 45,
	"Moonglade" => 46,
	"Shadowmoon Valley" =>47,
	"Tirisfal Glades" => 48,
	"Azshara" => 49,
	"Redridge Mountains" => 50,
	"Bloodmyst Isle" => 51,
	"Western Plaguelands" => 52,
	"Alterac Mountains" => 53,
	"Westfall" => 54,
	"Duskwood" => 55,
	"Netherstorm" => 56,
	"Ghostlands" => 57,
	"Zangarmarsh" => 58,
	"Desolace" => 59,
	"Kalimdor" => 60,
	"Searing Gorge" => 61,
	"Outland" => 62,
	"Feralas" => 63,
	"Hillsbrad Foothills" => 64,
}
rare_map = {
  	204 => [202], # silver
  	205 => [203,206], # gold
  	208 => [206,214,215], # truesilver
  	209 => [212,213,207], # oozed covered silver
  	210 => [212,213,207], # ooze covered gold
  	211 => [212,213,207], # oozed covered true silver
  	217 => [206,214,215], # dark iron
  	224 => [222,223,221], # khorium
  	223 => [222],
  	441 => [440] #flame cap
}
rare_src = {
  202 => [204],
  203 => [205,206],
  206 => [208,217],
  214 => [208,217],
  215 => [208,217],
  207 => [209,210,211],
  212 => [209,210,211],
  213 => [209,210,211],
  440 => [441],
  222 => [224,223],
  223 => [224],
  221 => [224]
}
# mieral viens
mineral_map = {
  "Copper Vein"                     => [1731,201],
  "Incendicite Mineral Vein"        => [1610,219],
  "Tin Vein"                        => [1732,202],
  "Lesser Bloodstone Deposit"       => [2653,218],
  "Iron Deposit"                    => [1735,203],
  "Mithril Deposit"                 => [2040,206],
  "Ooze Covered Mithril Deposit"    => [123310,207],
  "Small Thorium Vein"              => [324,214],
  "Ooze Covered Thorium Vein"       => [123848,213],
  "Rich Thorium Vein"               => [175404,215],
  "Fel Iron Deposit"                => [181555,221],
  "Adamantite Deposit"              => [181556,222],
  "Rich Adamantite Deposit"         => [181569,223],
  "Khorium Vein"                    => [181557,224],
  "Nethercite Deposit"              => [185877,227],
  # rare nodes below
  "Silver Vein"                     => [1733,204],
  "Ooze Covered Silver Vein"        => [73940,209],
  "Ooze Covered Rich Thorium Vein"  => [177388,212],
  "Dark Iron Deposit"               => [165658,217],
  "Truesilver Deposit"              => [2047,208],
  "Ooze Covered Truesilver Deposit" => [123309,211],
  "Gold Vein"                       => [1734,205],
  "Ooze Covered Gold Vein"          => [73941,210],
  }
# Herbs
herb_map = {
  "Silverleaf" 			    => [1617,402],
  "Peacebloom" 			    => [1618,401],
  "Bloodthistle"		    => [181166,436],
  "Earthroot"			    	=> [1619,403],
  "Mageroyal" 		    	=> [1620,404],
  "Briarthorn" 		    	=> [1621,405],
  "Stranglekelp" 		  	=> [2045,407],
  "Bruiseweed" 			    => [1622,408],
  "Wild Steelbloom" 		=> [1623,409],
  "Grave Moss" 			    => [1628,410],
  "Kingsblood" 			    => [1624,411],
  "Liferoot" 				    => [2041,412],
  "Fadeleaf" 				    => [2042,413],
  "Goldthorn" 				  => [2046,414],
  "Khadgar's Whisker" 	=> [2043,415],
  "Wintersbite" 			  => [2044,416],
  "Firebloom" 				  => [2866,417],
  "Purple Lotus" 			  => [142140,418],
  "Arthas' Tears" 			=> [142141,420],
  "Sungrass" 				    => [142142,421],
  "Blindweed" 				  => [142143,422],
  "Ghost Mushroom" 		  => [142144,423],
  "Gromsblood" 			    => [142145,424],
  "Golden Sansam" 			=> [176583,425],
  "Dreamfoil" 				  => [176584,426],
  "Mountain Silversage" => [176586,427],
  "Plaguebloom" 			  => [176587,428],
  "Icecap" 				      => [176588,429],
  "Black Lotus" 			  => [176589,431],
  "Felweed" 				    => [181270,432],
  "Dreaming Glory" 		  => [181271,433],
  "Terocone" 			  	  => [181277,434],
  "Ragveil" 				    => [181275,440],
  "Flame Cap" 			  	=> [181276,441],
  "Netherbloom" 		  	=> [181279,438],
  "Nightmare Vine" 	  	=> [181280,439],
  "Mana Thistle" 		  	=> [181281,437],
  "Netherdust Bush"     => [185881,442],
}
treasure_map = {
  "Giant Clam" 						    => [2744,501],
	"Battered Chest" 				    => [2843,502],
	"Tattered Chest" 				    => [2844,503],
	"Solid Chest" 					    => [2850,504],
	"Large Iron Bound Chest"    => [74447,505],
	"Large Solid Chest" 			  => [74448,506],
	"Large Battered Chest"		  => [75293,507],
	"Buccaneer's Strongbox" 	  => [123330,508],
	"Large Mithril Bound Chest" => [153468,509],
	"Large Darkwood Chest" 			=> [131979,510],
	"Un'Goro Dirt Pile" 				=> [157936,511],
	"Bloodpetal Sprout" 				=> [164958,512],
	"Blood of Heroes" 				  => [176213,513],
	"Practice Lockbox" 			  	=> [178244,514],
	"Battered Footlocker" 		  => [179488,515],
	"Waterlogged Footlocker" 	  => [179487,516],
	"Dented Footlocker" 			  => [179496,517],
	"Mossy Footlocker" 				  => [179497,518],
	"Scarlet Footlocker" 			  => [179498,519],
	"Burial Chest" 					    => [181665,520],
	"Fel Iron Chest" 					  => [181798,521],
	"Heavy Fel Iron Chest" 		  => [181800,522],
	"Adamantite Bound Chest" 	  => [181802,523],
	"Felsteel Chest" 					  => [181804,524],
	"Glowcap" 						      => [182053,525],
	"Wicker Chest" 					    => [184740,526],
	"Primitive Chest" 				  => [184793,527],
	"Solid Fel Iron Chest" 		  => [184930,528],
	"Bound Fel Iron Chest" 		  => [184931,529],
	"Bound Adamantite Chest" 	  => [184936,530],
	"Netherwing Egg" 					  => [185915,531],
}
def get_data(id)
  response = Net::HTTP.get(URI.parse("http://www.wowhead.com/?object=#{id}"))
  unless response
    raise "Data not available"
  end
  lst = response.scan(/(<a href="javascript:;" onclick="myMapper\.update\(\{zone: \d+, coords: \[(.*)\])/)[0]
  if lst.nil?
    raise "No map data for #{id}"
  end
  return lst[0].split(/<a href="javascript:;"/)
end

def get_zone_name(zone_id,zm,zone_map)
  if zm[zone_id]
    return zm[zone_id]
  else
    response = Net::HTTP.get(URI.parse("http://www.wowhead.com/?zone=#{zone_id}"))
    response =~ /\<title\>(\w.*) - (\w.*) - (\w.*)\<\/title\>/
    name = Regexp.last_match(1)
    if name
      name.rstrip!
      zm[zone_id] = name
      return name
    else
      raise "Zone #{zone_id} could not be parsed"
    end
  end
end

def process_javascript(script_line,storage,node_type,zm,zmap, rare_map, rare_src)
  zn = script_line.scan(/zone: (\d+)/)
  zone = get_zone_name(zn,zm,zmap)
  if zone != nil
    puts "Zone #{zone}"
    zone.to_s.tr!("\\","")
    if zmap[zone] != nil
    else
      puts "bad zone #{zone} as zn #{zn}"
    end
    zone = zmap[zone]
    coordinates = script_line.scan(/\[(\d+\.?\d?)\,(\d+\.?\d?)\]/)
    coordinates.each {|pair|
    id = gather_coords(pair[0].to_f,pair[1].to_f)
    unless storage[zone]
      storage[zone] = Hash.new
    end
    if storage[zone].has_key?(id) #TODO rare spawn checks here
      if rare_map.has_key?(node_type)
        if rare_map[node_type].include?(storage[zone][id]) # we didnt find the normal spawn that makes this rare
          #puts "Duplicate coords found for #{id} original type is #{storage[zone][id]} new type is #{node_type}"
        elsif rare_map.include?(storage[zone][id]) and rare_map[storage[zone][id]].include?(node_type)
          storage[zone][id] = node_type
          #puts "we had a rare already in storage, but found the normal overriding"
        end
        #puts "Duplicate coords found Orig: #{storage[zone][id]} New: #{node_type}"
      elsif rare_src.has_key?(node_type) and rare_src[node_type].include?(storage[zone][id])
        storage[zone][id] = node_type
        #puts "replacing rare spawn #{storage[zone][id]} with this normal node #{node_type}"
      else
        puts "Dup found not part of rare mappings Orig:#{storage[zone][id]} new:#{node_type}"
      end
    else
        storage[zone][id] = node_type
    end
    if block_given?
      yield
    end
  }
  else
    raise "Could find Zone #{zone}"
  end
end
def gather_coords(x,y)
  trim_terminator = 7
  if y == 100
    y = 99.9
  end
  if x == 100
    x = 99.9
  end
  id = (( (x * 1000) + 0.5).floor * 1000) + (y * 100 + 0.5).floor
  #id = ((x*100000000).round + (y*10000).round).to_s[0..trim_terminator].to_i
  #puts "input x,y = #{x},#{y} (#{id})"
  return id
end

def process_mapline(line,zoneid,node_id, map)
  offset = 0
  length = 6
  lineLength = line.length
  map[zoneid] = Hash.new
  while offset < lineLength
    x = "#{line[offset,2]}.#{line[offset+2,1]}"
    y = "#{line[offset+3,2]}.#{line[offset+5,1]}"
    offset = offset + 6
    map[zoneid][gather_coords(x.to_f,y.to_f)] = node_id
  end
end
# Main program below
# start time 78009000
start_time = Time.new

mining_sv_file = File.new("MiningData.lua", modestring="w")
herb_sv_file = File.new("HerbalismData.lua", modestring="w")
gas_sv_file = File.new("GasData.lua", modestring="w")
treasure_sv_file = File.new("TreasureData.lua", modestring="w")
count1 = 0
count2 = 0
zones = {}

start_time1 = Time.new
mineral_map.keys.sort.each {|k|
    id = mineral_map[k]
    puts "Processing Mineral #{k}"
    begin
      data = get_data(id[0])
      data.each {|d|
        if d.length < 1
          next
        end
        begin
          process_javascript(d,minerals,id[1],zones,zone_map, rare_map, rare_src) {count1 += 1}
        rescue Exception => p
          puts "Processing error for #{k} == #{p}"
        end
      }
    rescue Exception => e
      puts(e)
    end
  }
mining_sv_file << "GatherMateDataMineDB = "
mining_sv_file << minerals.to_lua
mining_sv_file.close
end_time1 = Time.new
puts "Processed #{count1} minerals in #{ (end_time1.to_i-start_time1.to_i) } seconds"

start_time2 = Time.new
herb_map.keys.sort.each {|k|
    id = herb_map[k]
    puts "Processing Herb #{k}"
    begin
      data = get_data(id[0])
      data.each {|d|
        if d.length < 1
          next
        end
        begin
          process_javascript(d,herbs,id[1],zones,zone_map, rare_map, rare_src){count2 += 1}
        rescue Exception => p
          puts "Processing error for #{k} == #{p}"
        end
      }
    rescue Exception => e
      puts(e)
    end
  }
herb_sv_file << "GatherMateDataHerbDB = "
herb_sv_file << herbs.to_lua
herb_sv_file.close
end_time2 = Time.new
puts "Processed #{count2} herbs in #{ (end_time2.to_i-start_time2.to_i) } seconds"

start_time2 = Time.new
treasure_map.keys.sort.each {|k|
    id = treasure_map[k]
    puts "Processing Treasure #{k}"
    begin
      data = get_data(id[0])
      data.each {|d|
        if d.length < 1
          next
        end
        begin
          process_javascript(d,treasure,id[1],zones,zone_map, rare_map, rare_src){count2 += 1}
        rescue Exception => p
          puts "Processing error for #{k} == #{p}"
        end
      }
    rescue Exception => e
      puts(e)
    end
  }
treasure_sv_file << "GatherMateDataTreasureDB = "
treasure_sv_file << treasure.to_lua
treasure_sv_file.close
end_time2 = Time.new
puts "Processed #{count2} treasure in #{ (end_time2.to_i-start_time2.to_i) } seconds"



gas_sv_file << "GatherMateDataGasDB = "
# windy clou
process_mapline("284611580780620760220340490660300590340270300620563436659555542225250281384308409244518217541242625394571471641462704433686652512299453596361811593714702522338394519829672770645669676590651590287366310667428526322629551644610646720652418293722697492302655640265423496275681565476380373256680619650739313260595417",21,301,gases) 
#Arcane vortex
process_mapline("568330401619430751518600531871643580699440332652492184238425231768384766408687332601272588301382457252588339610374724394411524422568514532562570616582633601654594617633580803536266397316646363458180410254720351663514511557341545309434405166630485608345579460306407660304297530",56,303,gases)
#felmist
process_mapline("614587614592613583568460466470570461522210525222384419389420642466634466646471640474642470638474518208467521471535581455495330420426469537214327533341349344622631649612466378430490560540300450620374542506450380350450280360431729570190328378342412",47,304,gases)
#swamp gas
process_mapline("580520650730590350240560160200437533460580302504607549329309090510280240300210310320320380340420381589450560630660750830780790850490160240330621601530826726844312713347269359270433650685119458415584808792402623382631603462281481132621185687673658866458388520",58,302,gases)
## Staticly adding gas clouds as reported on Wowhead
# http://www.wowhead.com/?maps=3518:250430580780620760220340490660300590340270300620563436659555542225 "Windy Cloud"
# http://www.wowhead.com/?maps=3523:568330401619430751518600531871643580699440332652 "Arcane Vortex"
# http://www.wowhead.com/?maps=3520:614587614592613583568460466470570461522210525222384419389420642466634466646471640474642470638474518208467521471535581455495330420426469537214327533341349344622631649612466378430490560540300450620374542506450380350450280360431729570190328378342412 "Felmist"
# http://www.wowhead.com/?maps=3521:580520650730590350240560160200440560460580302504607549329309090510280240300210310320320380340420381589450560630660750830780790850490  "Swamp Gas"
gas_sv_file << gases.to_lua
gas_sv_file.close


count = count1.to_i + count2.to_i
end_time = Time.new
puts "Processed a total of #{count} objects in #{ (end_time.to_i-start_time.to_i) } seconds"
