(**************************************************************************)
(*                                                                        *)
(*  Copyright (C) 2012 Johannes 'josch' Schauer <j.schauer@email.de>      *)
(*  Copyright (C) 2012 Pietro Abate <pietro.abate@pps.jussieu.fr>         *)
(*                                                                        *)
(*  This library is free software: you can redistribute it and/or modify  *)
(*  it under the terms of the GNU Lesser General Public License as        *)
(*  published by the Free Software Foundation, either version 3 of the    *)
(*  License, or (at your option) any later version.  A special linking    *)
(*  exception to the GNU Lesser General Public License applies to this    *)
(*  library, see the COPYING file for more information.                   *)
(**************************************************************************)

open ExtLib
open Common

module IntSet = BootstrapCommon.IntSet

module Make (U : sig val univ : Cudf.universe end) = struct
  module G = SrcGraph.G

  let self_cycles binset g = G.fold_edges_e (fun (v1,label,v2) (type1, type2, type3) ->
    match v1,v2 with
      | SrcGraph.SrcPkg sid1, SrcGraph.SrcPkg sid2 ->
          if sid1 = sid2 then begin
            let srcpkg = CudfAdd.inttovar U.univ sid1 in
            (* first decide whether the edge is strong or not *)
            if IntSet.is_empty label.SrcGraph.strong then begin
              let el = (srcpkg,List.map (CudfAdd.inttovar U.univ) (IntSet.elements !(label.SrcGraph.binaries))) in
              (type1, type2, el::type3)
            end else begin
              let el = (srcpkg,
                        List.map (CudfAdd.inttovar U.univ) (IntSet.elements label.SrcGraph.strong),
                        List.map (CudfAdd.inttovar U.univ) (IntSet.elements label.SrcGraph.strong_direct)) in
              (* check whether some of the strong dependencies are built by the 
               * source package*)
              let selfbuilt =
                let bins = List.fold_left (fun acc pkg ->
                  IntSet.add (CudfAdd.vartoint U.univ pkg) acc
                ) IntSet.empty (binset srcpkg) in
                not (IntSet.is_empty (IntSet.inter bins label.SrcGraph.strong_direct))
              in
              if selfbuilt then begin
                (el::type1,type2,type3)
              end else begin
                (type1,el::type2,type3)
              end
            end
          end else (type1, type2, type3)
      | _ -> failwith "not implemented"
  ) g ([],[],[])
end
