#!/usr/bin/env python

from sqlalchemy import *
from debian import deb822
import gzip

unbuildable = []
buildable = []
#FIXME: support it in configure file or command line options
arch=['linux-any', 'mipsel', 'any']
multilib=['-amd64', '-i386', '-mips64', '-mipsn32', '-multilib', 'lib32', 'lib64', 'libn32', 'libx32']



def include_provides(dct, inst):
	prov=inst.get('Provides')
	if not prov:
		return 0
	for i in prov.split(', '):
		dct[i]=inst
	return 0

def to_dict(pkgs):
	dct= {}
	for i in pkgs:
		dct[i['Package']]=i;
		include_provides(dct, i)
	return dct

def in_multilib(pkg):
	for i in multilib:
		if i in pkg:
			return True
	return False


def parse_builddeps(line, arch):
	deps = set()
	for i in line.split(', '):
		dep_pkg = i.split(' ')[0]
		#FIXME: support it in configure file or command line options
		if in_multilib(dep_pkg):
	 		continue
		if '[' not in i:
			deps |= set([dep_pkg])
			continue
		ax=i.split('[')[1].split(']')[0].split(' ')
		#FIXME: support [!arch]
	 	if '!' in ax[0] or list(set(arch) & set(ax)):
			deps |= set([dep_pkg])
	return deps

#FIXME: support version check
def parse_deps(line):
	deps = set()
	if not line:
		return deps
	for i in line.split(', '):
		dep_pkg = i.split(' ')[0]
		deps |= set([dep_pkg])
	return deps


def get_builddeps(src, src_dict, arch):
	seg = src_dict.get(src, None)
	if not seg:
		return ''
	line = seg.get('Build-Depends', '')
	return parse_builddeps(line, arch)

def merge_list(a, b):
	for i in b:
		if i not in a:
			a.append(i)
	return a


def is_installable(pkg, bin_dict):
	if in_multilib(pkg):
		return set()
	if pkg not in bin_dict:
		return set([pkg])
	depsx = parse_deps(bin_dict.get(pkg,dict()).get('Depends'))
	depsx |= parse_deps(bin_dict.get(pkg,dict()).get('Pre-Depends'))
	if len(depsx) == 0:
		return set()
	
	a = 1
	err = set()
	deps = list(depsx)
	while a < len(deps):
		deps = merge_list(deps, parse_deps(bin_dict.get(deps[a], dict()).get('Depends')))
		deps = merge_list(deps, parse_deps(bin_dict.get(deps[a], dict()).get('Pre-Depends')))
		a+=1
	for i in deps:
		if i not in bin_dict.keys():
			err |= set([i])
	return err
		
def is_buildable(src, builddep, bin_dict):
	err = set()
	for i in builddep:
		err |= is_installable(i, bin_dict)
	return err

def get_source(src_dict, pkgs):
	ret=set()
	for j in src_dict:
		bp=src_dict[j]['Binary'].split(', ')
		if set(pkgs) & set(bp):
			ret |= set([j])
	return ret

def add_to_sql(src, src_dict, connection):
	b=src+'_'+src_dict[src]['Version']
	sql_cmd="UPDATE {0} SET status='{1}' WHERE pkg_v LIKE '{2}' AND pkg_v!='{3}' AND status='waiting'".format('mips64el', 'new-version', src+'_%%', b)
	result = connection.execute(sql_cmd)
	sql_cmd="INSERT IGNORE INTO %s VALUES('%s','%s', NULL, NULL, NULL)" % ('mips64el', b, 'waiting')
	result = connection.execute(sql_cmd)

def detect_buildable(src, src_dict, arch, bin_dict, connection, src_set):
	if src_dict[src]['Architecture'] == 'all':
		return 0
	#	sql_cmd="INSERT IGNORE INTO %s VALUES('%s','%s', NULL, NULL, NULL)" % ('mips64el', b, 'skipped-arch')
	#	result = connection.execute(sql_cmd)
	build_depends = get_builddeps(src, src_dict, arch)
	err = is_buildable(src, build_depends, bin_dict)
	if err == set([]) or err == set(['']):
		add_to_sql(src, src_dict, connection)
		return 0
	for i in get_source(src_dict, err):
		src_set |= set([i])
	print "%s:  %s" %(src, err)
	return 1
		
#FIXME: support it in configure file or command line options
sources_filename='/home/repo/mips64el/dists/sid/main/source/Sources.gz'
source = deb822.Packages.iter_paragraphs(gzip.open(sources_filename))
src_dict = to_dict(source)

#FIXME: support it in configure file or command line options
packages_filename='/home/repo/mips64el/dists/sid/main/binary-mips64el/Packages.gz'
binary = deb822.Packages.iter_paragraphs(gzip.open(packages_filename))
bin_dict = to_dict(binary)

sql_engine = create_engine("mysql://user:password@192.168.252.248/buildd")
connection = sql_engine.connect()

basef = open('base.list', 'rw+')
src_set=set()
to_build_bin = basef.readlines()
for pkg_x in to_build_bin:
	src=pkg_x.strip()
	src_set |= set([src])
	detect_buildable(src, src_dict, arch, bin_dict, connection, src_set)
print src_set

basef.seek(0)
for i in src_set:
	basef.write(i+'\n')
