# -*- coding: utf-8 -*-
#
# Gramps - a GTK+/GNOME based genealogy program
#
# Copyright (C) 2003-2004  Donald N. Allingham
#
# 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

# $Id: rel_no.py,v 1.1.2.5 2004/12/12 18:48:32 jemtland Exp $

# Written by Alex Roitman, largely based on Relationship.py by Don Allingham
# and on valuable input from Frode Jemtland

#-------------------------------------------------------------------------
#
# GRAMPS modules
#
#-------------------------------------------------------------------------

import RelLib
from gettext import gettext as _

#-------------------------------------------------------------------------
#
# Norwegian-specific definitions of relationships
#
#-------------------------------------------------------------------------

_cousin_level = [ "", "", #brother/sister, fetter/kusine -- these are taken care of separately
"tremenning", "firemenning", "femmenning", 
"seksmenning", "sjumenning", "åttemenning",
"nimenning", "timenning", "elvemenning", 
"tolvmenning", "tretenmenning", "fjortenmenning",
"femtenmenning", "sekstenmenning", "syttenmenning",
"attenmenning", "nittenmenning", "tyvemenning" ] 

_cousin_terms = _cousin_level + ["fetter","kusine"]
#-------------------------------------------------------------------------
#
#
#
#-------------------------------------------------------------------------
def get_parents(level):
    if level == 0:
        return "forelder"
    else:
        return "aner i %d. generasjon" % (level+1)

def get_cousin(level):
    if level>len(_cousin_level)-1:
        # FIXME: use Norwegian term term here, 
	# UPDATED by Frode: unsure about the expresion "en fjern slektning", should it be just "fjern slektning".
	# Need to see it used in the program to get the understanding.
        return "en fjern slektning"
    else:
        return _cousin_level[level]

def pair_up(rel_list):
    result = []
    item = ""
    for word in rel_list[:]:
        if not word:
            continue
        if word in _cousin_terms:
            if item:
                result.append(item)
                item = ""
            result.append(word)
            continue
        if item:
            if word == 'sønne':
                word = 'sønn'
            result.append(item + word)
            item = ""
        else:
            item = word
    if item:
        result.append(item)
    gen_result = [ item + 's' for item in result[0:-1] ]
    return ' '.join(gen_result+result[-1:])

def get_direct_ancestor(person,rel_string):
    result = []
    for ix in range(len(rel_string)):
        if rel_string[ix] == 'f':
            result.append('far')
        else:
            result.append('mor')
    return pair_up(result)

def get_direct_descendant(person,rel_string):
    result = []
    for ix in range(len(rel_string)-2,-1,-1):
        if rel_string[ix] == 'f':
            result.append('sønne')
        else:
            result.append('datter')
    if person.getGender() == RelLib.Person.male:
        result.append('sønn')
    else:
        result.append('datter')
    return pair_up(result)

def get_ancestors_cousin(person,rel_string_long,rel_string_short):
    result = []
    removed = len(rel_string_long)-len(rel_string_short)
    level = len(rel_string_short)-1
    for ix in range(removed):
        if rel_string_long[ix] == 'f':
            result.append('far')
        else:
            result.append('mor')
    if level > 1:
        result.append(get_cousin(level))
    elif person.getGender() == RelLib.Person.male:
        result.append('fetter')
    else:
        result.append('kusine')
    main_string = get_two_way_rel(person,rel_string_short,rel_string_long)
    aux_string = pair_up(result)
    return "%s (%s)" % (main_string,aux_string)

def get_cousins_descendant(person,rel_string_long,rel_string_short):
    result = []
    aux_string = ""
    removed = len(rel_string_long)-len(rel_string_short)-1
    level = len(rel_string_short)-1
    if level > 1:       # Cousin terms without gender
        result.append(get_cousin(level))
    elif level == 1:    # gender-dependent fetter/kusine
        if rel_string_long[removed] == 'f':
            result.append('fetter')
        else:
            result.append('kusine')
    elif rel_string_long[removed] == 'f':
        result.append('bror')
    else:
        result.append('søster')
    for ix in range(removed-1,-1,-1):
        if rel_string_long[ix] == 'f':
            result.append('sønn')
        else:
            result.append('datter')
    if person.getGender() == RelLib.Person.male:
        result.append('sønn')
    else:
        result.append('datter')
    main_string = get_two_way_rel(person,rel_string_long,rel_string_short)
    if level:
        aux_string = " (%s)" % pair_up(result)
    return "%s%s" % (main_string,aux_string)

def get_ancestors_brother(rel_string):
    result = []
    for ix in range(len(rel_string)-1):
        if rel_string[ix] == 'f':
            result.append('far')
        else:
            result.append('mor')
    result.append('bror')
    return pair_up(result)

def get_ancestors_sister(rel_string):
    result = []
    for ix in range(len(rel_string)-1):
        if rel_string[ix] == 'f':
            result.append('far')
        else:
            result.append('mor')
    result.append('søster')
    return pair_up(result)

def get_two_way_rel(person,first_rel_string,second_rel_string):
    result = []
    for ix in range(len(second_rel_string)-1):
        if second_rel_string[ix] == 'f':
            result.append('far')
        else:
            result.append('mor')
    if len(first_rel_string)>1:
        if first_rel_string[-2] == 'f':
            result.append('bror')
        else:
            result.append('søster')
        for ix in range(len(first_rel_string)-3,-1,-1):
            if first_rel_string[ix] == 'f':
                result.append('sønne')
            else:
                result.append('datter')
        if person.getGender() == RelLib.Person.male:
            result.append('sønn')
        else:
            result.append('datter')
    else:
        if person.getGender() == RelLib.Person.male:
            result.append('bror')
        else:
            result.append('søster')
    return pair_up(result)

def is_spouse(orig,other):
    for f in orig.getFamilyList():
        if other == f.getFather() or other == f.getMother():
            return 1
    return 0

def apply_filter(person,rel_str,plist,pmap):
    if person == None:
        return
    plist.append(person)
    pmap[person.getId()] = rel_str
    
    family = person.getMainParents()
    if family:
        apply_filter(family.getFather(),rel_str+'f',plist,pmap)
        apply_filter(family.getMother(),rel_str+'m',plist,pmap)

def get_relationship(orig_person,other_person):
    """
    Returns a string representing the relationshp between the two people,
    along with a list of common ancestors (typically father,mother) 
    
    Special cases: relation strings "", "undefined" and "spouse".
    """

    firstMap = {}
    firstList = []
    secondMap = {}
    secondList = []
    common = []
    rank = 9999999
    
    if orig_person == None:
        return ("undefined",[])
    
    firstName = orig_person.getPrimaryName().getRegularName()
    secondName = other_person.getPrimaryName().getRegularName()
    
    if orig_person == other_person:
        return ('', [])
    if is_spouse(orig_person,other_person):
#        return ('spouse', [])
#    FIXME: need Norwegian term for spouse. If gender-specific, use the code below.
#    UPDATE by Frode: unsure about how it's included in the finished code, so I need 
#    to see this running to know if it is the right words to use.
        if other_person.getGender() == RelLib.Person.male:
            return ("ektemann",[])
        else:
            return ("hustru",[])

    try:
        apply_filter(orig_person,'',firstList,firstMap)
        apply_filter(other_person,'',secondList,secondMap)
    except RuntimeError,msg:
        return (_("Relationship loop detected"),None)
    
    for person in firstList:
        if person in secondList:
            new_rank = len(firstMap[person.getId()])
            if new_rank < rank:
                rank = new_rank
                common = [ person ]
            elif new_rank == rank:
                common.append(person)

    if common:
        person = common[0]
        secondRel = firstMap[person.getId()]
        firstRel = secondMap[person.getId()]
    else:
        return ("",[])

    if not firstRel:
        if not secondRel:
            return ('',common)
        else:
            return (get_direct_ancestor(other_person,secondRel),common)
    elif not secondRel:
        return (get_direct_descendant(other_person,firstRel),common)
    elif len(firstRel) == 1:
        if other_person.getGender() == RelLib.Person.male:
            return (get_ancestors_brother(secondRel),common)
        else:
            return (get_ancestors_sister(secondRel),common)
    elif len(secondRel) >= len(firstRel):
        return (get_ancestors_cousin(other_person,secondRel,firstRel),common)
    else:
        return (get_cousins_descendant(other_person,firstRel,secondRel),common)


def get_grandparents_string(orig_person,other_person):
    """
    returns a string representing the relationshp between the two people,
    along with a list of common ancestors (typically father,mother) 
    """
    firstMap = {}
    firstList = []
    secondMap = {}
    secondList = []
    common = []
    rank = 9999999

    if orig_person == None:
        return ("undefined",[])

    if orig_person == other_person:
        return ('', [])

    try:
        apply_filter(orig_person,'',firstList,firstMap)
        apply_filter(other_person,'',secondList,secondMap)
    except RuntimeError,msg:
        return (_("Relationship loop detected"),None)
    
    for person in firstList:
        if person in secondList:
            new_rank = len(firstMap[person.getId()])
            if new_rank < rank:
                rank = new_rank
                common = [ person ]
            elif new_rank == rank:
                common.append(person)

    if common:
        person = common[0]
        secondRel = firstMap[person.getId()]
        firstRel = secondMap[person.getId()]
    else:
        return ('', [])

    if not firstRel:
        if not secondRel:
            return ('',common)
        else:
            return (get_parents(len(secondRel)),common)
    else:
        return None

#-------------------------------------------------------------------------
#
# Register this function with the Plugins system 
#
#-------------------------------------------------------------------------
from Plugins import register_relcalc, register_parents

register_relcalc(get_relationship,
    ["nb","nn","no", "nb_NO","nn_NO","no_NO","nb_NO.UTF8","nn_NO.UTF8","no_NO.UTF8",
    "nb_NO.UTF-8","nn_NO.UTF-8","no_NO.UTF-8", 
    "nb_NO.utf-8","nn_NO.utf-8","no_NO.utf-8", 
    "nb_NO.iso88591","nn_NO.iso88591","no_NO.iso88591", 
    "nynorsk","Nynorsk"])

register_parents(get_grandparents_string,
    ["nb","nn","no", "nb_NO","nn_NO","no_NO","nb_NO.UTF8","nn_NO.UTF8","no_NO.UTF8",
    "nb_NO.UTF-8","nn_NO.UTF-8","no_NO.UTF-8", 
    "nb_NO.utf-8","nn_NO.utf-8","no_NO.utf-8", 
    "nb_NO.iso88591","nn_NO.iso88591","no_NO.iso88591", 
    "nynorsk","Nynorsk"] 
)
