import urllib
import md5
import os
import sys
import random
import shutil

import version
import wine
import drives
import i5comp
import _7za

random.seed()

class Installer:
    longname = "Worms Armageddon"
    shortname = "worms_armageddon"
    
    #appdir = "c:\program files\worms armageddon"
    appdir = None
    
    #appversion = 3, 6, 26, 5 - the version currently installed
    appversion = 0,
    
    #version = 3, 6, 26, 5 - the version we want
    version = 3, 6, 26, 5
    
    #cddrive = "d:"
    cddrive = None
    
    #cdversion = "V1.05E"
    cdversion = None
    
    language = "English"    #FIXME: provide a way to set this
    languages = ("English", "French", "Portuguese", "Spanish") #FIXME: does this change by cd?
    
    patch_info = (
        (
            "ftp://ftp.team17.com/pub/t17/patches/pc/WAPatch.exe",
            "http://www.pobox.com/~skeet/worms/wa/WAPatch.exe",
            "ftp://ftp.inet.fi/TheDome/download/WAPatch.exe",
            "http://team17.rinux.net/patches_pc/WAPatch.exe",
            "http://www.dream17.co.uk/WAPatch.exe",
            "http://madewokherd.nfshost.com/worms/WAPatch.exe",
            ),
        "WAPatch.exe",
        "1ecac74d897d0535e8ea3b9b2dafac53",
        )
    
    update_info = (
        (
            "ftp://ftp.team17.com/pub/t17/patches/pc/WA_Update-3.6.26.5_Beta.exe",
            "http://www.nanacide.com/wahelp/WA_Update-3.6.26.5_Beta.exe",
            "http://www.clansfx.co.uk/downloads/WA_Update-3.6.26.5_Beta.exe",
            "http://team17.rinux.net/patches_pc/WA_Update-3.6.26.5_Beta.exe",
            "http://www.dream17.co.uk/WA_Update-3.6.26.5_Beta.exe",
            "http://madewokherd.nfshost.com/worms/WA_Update-3.6.26.5_Beta.exe",
            ),
        "WA_Update-3.6.26.5_Beta.exe",
        "329d91a53e7628e8c9dccc56ed8d562d",
        )
    
    def detectcd(self):
        if self.cdversion != None:
            return
        for drive in drives.get_drives():
            try:
                f = open(os.path.join(drive, "Data\\Resource\\version.txt"),'r')
                data = f.read()
                f.close()
            except:
                continue
            if data in ('V1.05E\n19-1-99\n', 'V3.00U\n26-5-99\n', 'V3.00E\n27-5-99\n'):
                self.cdversion = data.splitlines()[0]
                self.cddrive = drive
                break
            else:
                print "Warning: unknown cd on %s" % drive
                print data
        else:
            raise Exception("Couldn't find cd.")
    
    def detectversion(self):
        try:
            ver = version.get_fileversion(os.path.join(self.appdir,"wa.exe"))
            ver = ver.replace(', ','.').split('.')
            self.appversion = tuple(int(x) for x in ver)
        except:
            self.appversion = 0,
    
    #def detectinstall(self):
    #    if self.appdir == None:
    #        self.appdir = "C:\\Games\\Worms Armageddon"
    #        try:
    #            os.makedirs(self.appdir)
    #        except OSError:
    #            pass
    #    if self.version == None:
    #        try:
    #            ver = version.get_fileversion(os.path.join(self.appdir),"wa.exe")
    #            ver = version.replace(', ','.').split('.')
    #            self.version = tuple(int(x) for x in ver)
    #        except:
    #            self.version = 0,
    
    def download_file(self, info):
        urls, filename, md5sum = info
        filename = os.path.join(self.appdir, filename)
        try:
            f = open(filename, 'rb')
            local_md5sum = md5.new(f.read()).hexdigest()
            f.close()
            if local_md5sum == md5sum:
                print "Found %s, md5sum looks good" % filename
                return filename
            else:
                print "Found %s, bad md5sum.." % filename
                os.remove(filename)
        except:
            pass
        urls = list(urls)
        random.shuffle(urls)
        for url in urls:
            try:
                print "Downloading %s.." % url
                urllib.urlretrieve(url, filename)
                print "Successfully got %s" % url
                return filename #FIXME: should I check the md5sum here?
            except:
                print "Download failed"
                continue
        else:
            raise
    
    def download_files(self):
        if self.version >= (3,) and self.appversion < (3,) and self.cdversion == "V1.05E":
            self.patch_file = self.download_file(self.patch_info)
        self.update_file = self.download_file(self.update_info)
    
    def install_files(self):
        if self.appversion > self.version:
            raise Exception("Cannot go back to an earlier version (yet).")
        if self.appversion < (1,) and self.version >= (1,): #we need files from the cd
            cabfile = os.path.join(self.cddrive, "Install\\data1.cab")
            print "Extracting files from %s.." % cabfile
            if self.cdversion == "V1.05E":
                i5comp.extract(cabfile, "Program Executable Files", self.appdir)
            elif self.cdversion == "V3.00U":
                i5comp.extract(cabfile, "US Program Files", self.appdir)
                i5comp.extract(cabfile, "US Soundbank Editor", os.path.join(self.appdir,"User"))
                i5comp.extract(cabfile, "US Intro Graphics", os.path.join(self.appdir,"Graphics"))
                #i5comp.extract(cabfile, "US Registration Program", self.appdir) #no one cares
            elif self.cdversion == "V3.00E":
                i5comp.extract(cabfile, "Program Executable Files", self.appdir)
                i5comp.extract(cabfile, "Europe Soundbank Editor", os.path.join(self.appdir,"User"))
            
            waexe = os.path.join(self.cddrive,"Install\\Install\\wa.exe")
            print "Copying %s to %s" % (waexe, self.appdir)
            shutil.copyfile(waexe, os.path.join(self.appdir,"wa.exe"))
            
            readme = os.path.join(self.cddrive, "Data\\Resource", self.language, "readme.rtf")
            print "Copying %s to %s" % (readme, self.appdir)
            shutil.copyfile(readme, os.path.join(self.appdir,"readme.rtf"))
            
            namesfile = os.path.join(self.cddrive, "Data\\Resource", self.language, "names.wdb")
            print "Copying %s to %s" % (namesfile, os.path.join(self.appdir, "User"))
            shutil.copyfile(readme, os.path.join(self.appdir, "User","readme.rtf"))
            
            speechdir = os.path.join(self.cddrive, "Data\\User\\Speech", self.language)
            print "Copying contents of %s to %s" % (namesfile, os.path.join(self.appdir, "User\\Speech"))
            shutil.copytree(speechdir, os.path.join(self.appdir, "User\\Speech"))
            
            for userdir in ("Fanfare", "SavedLevels", "Schemes", "Support", "Games"):
                userdir = os.path.join(self.appdir, "User", userdir)
                print "Creating %s" % userdir
                os.mkdir(userdir)
        self.detectversion()
        if self.appversion < (3,) and self.version >= (3,):
            print "Extracting files from WAPatch.exe"
            #don't use 7za.extract because we only need one file
            cmdline = '"%s" e "%s" data1.cab' % (_7za._7ZA_EXE, os.path.join(self.appdir, 'WAPatch.exe'))
            print cmdline
            os.system(cmdline)
            i5comp.extract("data1.cab", "Program Executable Files", self.appdir)
        self.detectversion()
        if self.appversion < (3, 6, 26, 5) and self.version >= (3, 6, 26, 5):
            print "Extracting files from WA_Update-3.6.26.5_Beta.exe"
            _7za.extract(os.path.join(self.appdir, "WA_Update-3.6.26.5_Beta.exe"), self.appdir)

if __name__ == '__main__':
#    if len(sys.argv) >= 2 and sys.argv[0] == '-i':
        i = Installer()
        i.detectcd()
        print "Enter a directory to install Worms Armageddon: "
        i.appdir = raw_input()
        #i.appdir = sys.argv[1]
        i.download_files()
        i.install_files()
