#!/usr/bin/env python

# Copyright (C) 2011 Fabiano Fidencio
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA.


from os import chdir, environ, getcwd, listdir, mkdir, path
from shutil import copy2, rmtree
from subprocess import PIPE, Popen
from sys import argv, exit
from argparse import ArgumentParser


contents_path = "abiword/AbiWord.app/Contents"

def environment_prepare():
    abisource_path="/tmp/abisource"
    mkdir(abisource_path, 0755)
    path = getcwd()
    chdir(abisource_path)
    return path

def environment_clean(path):
    chdir(path)
    abisource_path="/tmp/abisource"
    rmtree(abisource_path)

def _macports_source_get():
    source = "https://distfiles.macports.org/MacPorts/MacPorts-2.0.0.tar.gz"
    cmd = "curl -O %s" % source
    p = Popen(cmd, shell=True)
    p.wait()

def _macports_source_extract():
    cmd = "tar xzvpf MacPorts-2.0.0.tar.gz"
    p = Popen(cmd, shell=True)
    p.wait()

def _macports_install():
    current_dir = getcwd()
    chdir("MacPorts-2.0.0")
    cmd = "./configure --prefix=/tmp/abisource/macports \
            && make \
            && sudo make install"
    p = Popen(cmd, shell=True)
    p.wait()
    chdir(current_dir)

def _macports_env():
    macports_path = "/tmp/abisource/macports/"
    envs = environ
    env = "%s/bin:%s/sbin:%s" % (macports_path, macports_path, envs["PATH"])
    return env

def _macports_sync():
    envs = _macports_env()
    cmd = "sudo port -v selfupdate"
    p = Popen(cmd, shell=True, env={"PATH":envs})
    p.wait()

def macports_install():
    _macports_source_get()
    _macports_source_extract()
    _macports_install()
    _macports_sync()

def dependencies_install():
    envs = _macports_env()
    pkgs = "cairo +quartz+no_x11 \
            pango +quartz+no_x11 \
            fribidi \
            libgsf +no_gnome \
            redland \
            wv +no_x11 \
            enchant \
            boost"
    cmd = "sudo port install %s" % pkgs
    p = Popen(cmd, shell=True, env={"PATH":envs})
    p.wait()

def _abiword_source_get():
    cmd = "svn co http://svn.abisource.com/abiword/trunk abiword"
    p = Popen(cmd, shell=True)
    p.wait()

def _abiword_fix_macports_path():
    cmd = "sed -i -e \
            's/\\/opt\\/local/\\/tmp\\/abisource\\/macports/g' \
            configure.in"
    p = Popen(cmd, shell=True)
    p.wait()

def _abiword_install():
    envs = _macports_env()
    current_dir = getcwd()
    chdir("abiword")
    _abiword_fix_macports_path()
    cmd = "./autogen.sh \
            --with-darwinports \
            --enable-maintainer-mode \
            --disable-static \
            --enable-shared \
            --enable-plugins=\"docbook epub latex openwriter openxml opml\" \
            && make && DESTDIR=`pwd` make install"
    p = Popen(cmd, shell=True, env={"PATH":envs})
    p.wait()
    chdir(current_dir)

def abiword_install():
    _abiword_source_get()
    _abiword_install()

def _dep_list_get(lib):
    #otool -L path
    cmd =  "otool -L %s " %lib
    #get all .dylib from otool -L
    cmd += "| grep macports | sed -e 's/.dylib.*$/.dylib/'"
    #remove white spaces before and after the lib path/name
    cmd += "| sed 's/^[ \t]*//;s/[ \t]*$//'"

    p = Popen(cmd, shell=True, stdout=PIPE)
    p.wait()
    stdout = p.communicate()

    return stdout[0].split('\n')[:-1]

def _rdeps_get():

    libabiword = ""
    libabiword_deps = []
    for content in listdir(contents_path + "/Frameworks"):
        if content.endswith(".dylib"):
            libabiword = contents_path + "/Frameworks/" + content
            libabiword_deps = _dep_list_get(libabiword)
            break

    plugins = []
    plugins_deps = []
    for content in listdir(contents_path + "/PlugIns"):
        if content.endswith(".so"):
            plugin = contents_path + "/PlugIns/" + content
            plugins.append(plugin)
            plugins_deps = _dep_list_get(plugin)

    abiword = contents_path + "/MacOS/AbiWord"
    abiword_deps = _dep_list_get(abiword)

    rdeps = []
    for lib in libabiword_deps:
        rdeps.append(lib)

    for lib in plugins_deps:
        if lib not in rdeps:
            rdeps.append(lib)

    for lib in abiword_deps:
        if lib not in rdeps:
            rdeps.append(lib)

    rdeps_deps = []
    for lib in rdeps:
        rdeps_deps += _dep_list_get(lib)

    for lib in rdeps_deps:
        if lib not in rdeps_deps:
            rdeps.append(lib)

    return rdeps, libabiword, abiword, plugins

def _rdeps_copy(rdeps):
    rdeps_path = contents_path
    mkdir(rdeps_path, 0755)

    n_rdeps = []
    for dep in rdeps:
        dep_path, dep_name = path.split(dep)
        copy2(dep, rdeps_path)
        d = "%s/%s" % (rdeps_path, dep_name)
        cmd = "chmod 755 " + d
        n_rdeps.append(d)
        p = Popen(cmd, shell=True)
        p.wait()

    return n_rdeps

def _fix(lib, new):
    dep_list = _dep_list_get(lib)

    for d in dep_list:
        d_path, d_name = path.split(d)
        n = "@executable_path/../Frameworks/rdeps/" + d_name
        cmd = "install_name_tool -change %s %s %s" % (d, n, lib)
        p = Popen(cmd, shell=True)
        p.wait()

    lib_path, lib_name = path.split(lib)
    cmd = "install_name_tool -id %s %s" % (new, lib)
    p = Popen(cmd, shell=True)
    p.wait()

def _rdeps_fix(rdeps):
    for r in rdeps:
        file_path, file_name = path.split(r)
        new = "@executable_path/../Frameworks/rdeps/" + file_name
        _fix(r, new)

def _libabiword_fix(libabiword):
    file_path, file_name = path.split(libabiword)
    new = "@executable_path/../Frameworks/" + file_name
    _fix(libabiword, new)

def _abiword_fix(abiword):
    file_path, file_name = path.split(abiword)
    new = "@executable_path/" + file_name
    _fix(abiword, new)

def _plugins_fix(plugins):
    for p in plugins:
        file_path, file_name = path.split(p)
        new = "@executable_path/../PlugIns/" + file_name
        _fix(p, new)

def do_app():
    rdeps, libabiword, abiword, plugins = _rdeps_get()
    n_rdeps = _rdeps_copy(rdeps)
    _rdeps_fix(n_rdeps)
    _libabiword_fix(libabiword)
    _abiword_fix(abiword)
    _plugins_fix(plugins)

def do_dmg():
    mkdir("dmg", 0755)
    cmd = "cp -a abiword/AbiWord.app dmg/"
    p = Popen(cmd, shell = True)
    p.wait()
    cmd = "ln -s /Applications dmg/"
    p = Popen(cmd, shell=True)
    p.wait()
    cmd = "hdiutil create \
            -srcfolder \"dmg\" \
            -volname \"AbiWord\" \
            -fs HFS+ \
            -fsargs \"-c c=64,a=16,e=16\" \
            -format UDRW \"AbiWord.dmg\""
    p = Popen(cmd, shell=True)
    p.wait()
    rmtree("dmg")
    copy2("AbiWord.dmg", environ["HOME"] + "/Desktop/")


if __name__ == "__main__":
    parser = ArgumentParser(description="Automated dmg generator")
    parser.add_argument("--macports_path",
                        action="store",
                        dest="macports_path",
                        help="This option will use your current macports' \
                              installation from MACPORTS_PATH.\n\
                              ATTENTION: Without this option, macports will \
                              be downloaded and installed in: \
                              /tmp/abisource/macports")

    parser.add_argument("--abisource_path",
                        action="store",
                        dest="abi_path",
                        default=False,
                        help="This option will consider that you have \
                              AbiWord's sources in your computer, located at \
                              ABISOURCE_PATH and want to build it and NOT a \
                              specific version from our SVN.")

    parser.add_argument("--abisource_revision",
                        action="store",
                        dest="abi_rev",
                        help="This option will get a specific revision from \
                              AbiWord's SVN. \
                              ATTETION: If this option isn't passed, SVN's \
                              trunk will be used.")

    parser.add_argument("--abiword_version",
                        action="store",
                        dest="abi_version",
                        help="This option will get a specific version from \
                              AbiWord's SVN. \
                              ATTETION: If this option isn't passed, SVN's \
                              trunk will be used.")


    parser.add_argument("--no_deps",
                        action="store_true",
                        dest="no_deps",
                        default=False,
                        help="This option won't install AbiWord's \
                              dependencies in your computer. So, is YOUR \
                              WORK install all needed dependencies. Of \
                              course, you'll need to install macports before.")

    parser.add_argument("--start_from_build",
                        action="store_true",
                        dest="start_from_build",
                        default=False,
                        help="This option will consider that you have \
                              macports and all AbiWord's dependencies \
                              installed. \
                              ATTENTION: This options will build AbiWord and \
                              create a dmg file. So, is REALLY NECESSARY \
                              that you pass --abisource_path option.")

    parser.add_argument("--start_from_app",
                        action="store",
                        dest="start_from_app",
                        help="This option will use a generated .app file \
                              to fix all linkage and put all nedded libs \
                              into .app in a specific folder. After that a \
                              dmg file will be created(Don't put '/' at the end of .app package path). \
                              ATTENTION: Is REALLY NECESSARY that you pass \
                              --macports_path option. Eg: python build_script.py --start_from_app /Users/abi/Abiword.app")

    parser.add_argument("--start_from_linkage_fixed",
                        action="store",
                        dest="start_from_linkage_fixed",
                        help="This option will use a generated .app file \
                              with linkage working properly to create a \
                              .dmg file.\
                              ATTENTION: Is REALLY NECESSARY that you pass \
                              --macports_path option.")

    if len(argv) < 2:
        parser.print_help()
        exit()
    else:
        args = parser.parse_args()
#	print args


current_dir = getcwd()

def cleanAndPrint():
	environment_clean(current_dir)
	print "****************************************************"
	print "* AbiWord.dmg was created in you ~/Desktop. Enjoy! *"
	print "****************************************************"

dict_args=vars(args)
print dict_args

if dict_args['start_from_app'] != None:
	contents_path = dict_args['start_from_app'] + "/Contents"
	do_app()
	do_dmg()
	print_text()
	exit()
else:
	environment_prepare()
	macports_install()
	dependencies_install()
	abiword_install()
	do_app()
	do_dmg()
	cleanAndPrint()
