(**************************************************************************)
(*                                                                        *)
(*  Ocamlviz --- real-time profiling tools for Objective Caml             *)
(*  Copyright (C) by INRIA - CNRS - Universite Paris Sud                  *)
(*  Authors: Julien Robert                                                *)
(*           Guillaume Von Tokarski                                       *)
(*           Sylvain Conchon                                              *)
(*           Jean-Christophe Filliatre                                    *)
(*           Fabrice Le Fessant                                           *)
(*  GNU Library General Public License version 2                          *)
(*  See file LICENSE for details                                          *)
(*                                                                        *)
(**************************************************************************)

open Ocamlviz

let p1 = Point.create "first"
let t1 = Time.create "t"
let tag = Tag.create ~size:true ~period:1000 "foo"

let list = ref []

let vint = ref 0
let vfloat = ref 0.
let vstring = ref ""
let vbool = ref true

let r = ref 1
let _ = Value.observe_int_ref  "another_ref" r
let t = ref 0

let h = Hashtable.observe "h" (Hashtbl.create 17)


let s = Value.observe_int_ref  "sinus" (ref 1)

let _ = Value.observe_int_fct  "vint" (fun () -> !vint)
let _ = Value.observe_float_fct  "vfloat" (fun () -> !vfloat)
let _ = Value.observe_string_fct  "vstring" (fun () -> !vstring)
let _ = Value.observe_bool_fct  "vbool" (fun () -> !vbool)


let h2 = Hashtable.observe "incr hash" ~period:1000 (Hashtbl.create 17)

let hash_cpt = ref 0

let fib n = 
  let r = Value.observe_int_ref  "obserbe_int_ref" (ref 1) in
  Value.observe_int_fct ~weak:true  "observe_int" (fun () -> !r);
  Value.observe_string "jane" "street";
  let rec fib n =
    Point.observe p1;
    decr r;
    
    let v = (n,!vint,!vfloat,!vstring,!vbool) in
    let v = if Random.int 1000 < 1 then Tag.mark tag v else v in
    
    list := v::!list;

    Hashtbl.add h2 !hash_cpt !hash_cpt;
    incr hash_cpt;
    
    if n <= 1 then 
      1
    else
      fib (n-1) + fib (n-2)
  in
  fib n

let fib2 n =
  let s1 = "jane" in
  let s2 = "street" in
  let s3 = "summer" in
  let s4 = "project" in
  Point.kill p1;
  Time.kill t1;
  Tag.kill tag;
  let p2 = Point.create "second" in
  let rec fb n =
    Point.observe p2;
    incr vint;
    if Random.int 1000000 < 1 
    then 
      begin
	vfloat:=!vfloat+. 1.2;
	vstring:= begin
	  match !vint mod 4 with
	    |0 -> s1
	    |1 -> s2
	    |2 -> s3
	    |3 -> s4
	    |_ -> assert false
	end;
	vbool:=not !vbool;
      end;

    let v = (n,!vint,!vfloat,!vstring,!vbool) in
    
    list := v :: !list;
    if Random.int 1000000 = 0 then list := [];
      
    if n <= 1 then 
      r := if !r = 1 then 1 + Random.int 10000 else if !r mod 2 = 0 then !r / 2 else 3 * !r + 1;
      
      incr t;
      s := truncate (50. +. 50. *. sin (float !t *. 0.000001));

        if n <= 1 then 
      1
    else
      fb (n-1) + fb (n-2)
  in
  fb n

let main () =
  let arg = int_of_string Sys.argv.(1) in
  init ();
  Value.observe_int "now_int" arg;
  Hashtbl.add h 0 arg;
  (* wait_for_connected_clients 1; *)

  log "%s first fib" "before";
  log "still before first fib";
  Time.start t1;
  ignore (Time.time "fib" fib 32);
  list := [];
  Time.stop t1;
  log "%s first fib, before second fib" "after";
  ignore (fib2 arg)

   

let () = 
  main ()


(*
Local Variables: 
compile-command: "unset LANG; make -C .. test-fib"
End: 
*)
