type t = float

let make ~frozen_core hf =
  let mo_basis = 
    MOBasis.of_hartree_fock hf
  in
  let epsilon =
    MOBasis.mo_energies mo_basis
  in
  let mo_class =
    MOClass.cas_sd mo_basis ~frozen_core 0 0
    |> MOClass.to_list
  in
  let eri = 
    MOBasis.ee_ints mo_basis
  in
  let inactives =
    List.filter (fun i ->
      match i with MOClass.Inactive _ -> true | _ -> false) mo_class
  and virtuals =
    List.filter (fun i ->
      match i with MOClass.Virtual _ -> true | _ -> false) mo_class
  in

  let rmp2 () = 
    List.fold_left (fun accu b ->
        match b with MOClass.Virtual b ->
          let eps = -. epsilon.{b} in
          accu +. 
          List.fold_left (fun accu a ->
              match a with MOClass.Virtual a ->
                let eps = eps -. epsilon.{a} in
                accu +. 
                List.fold_left (fun accu j ->
                    match j with MOClass.Inactive j ->
                      let eps = eps +. epsilon.{j} in
                      accu +. 
                      List.fold_left (fun accu i ->
                          match i with MOClass.Inactive i ->
                            let eps = eps +. epsilon.{i} in
                            let ijab = ERI.get_phys eri i j a b
                            and abji = ERI.get_phys eri a b j i in
                            let abij =  ijab in
                            accu +. ijab *. ( abij +. abij -. abji) /. eps 
                                    | _ -> accu
                        ) 0. inactives
                              | _ -> accu
                  ) 0. inactives
                        | _ -> accu
            ) 0. virtuals
                  | _ -> accu
      ) 0. virtuals
  in


  match HartreeFock.kind hf with
  | HartreeFock.RHF   -> rmp2 ()
  | _ -> failwith "Not implemented"


