import std/[asyncdispatch, httpclient]
import std/json
import std/options
import strformat
import jester
from os import sleep
import httpcore, net, times, strutils

# Setup joplin_ping data
type
  joplin_ping* = object
    ping_result*: seq[string]
    ping_status*: bool
    req*: Request

# Setup joplin_tags data
type
  joplin_tags* = object
    id*, parent_id*, title*: seq[string]
    created_time*, updated_time*, user_created_time*, user_updated_time*, is_shared*: seq[int] 
    req*: Request

# Setup joplin_notebooks data
type
  joplin_notebooks* = object    
    id*, parent_id*, title*, share_id*, icon*: seq[string]
    created_time*, updated_time*, user_created_time*, user_updated_time*, is_shared*: seq[int] 
    req*: Request

# Setup joplin_notes data
type
  joplin_notes* = object    
    id*, parent_id*, title*, body*, author*, source_url*, source*, source_application*, application_data*, share_id*, conflict_original_id*, body_html*, base_url*: seq[string]
    created_time*, updated_time*, is_conflict*, is_todo*, todo_due*, todo_completed*, user_created_time*, user_updated_time*, markup_language*, is_shared*: seq[int]
    latitude*, longitude*, altitude*, order*:seq[float] 
    req*: Request

let
  resetDuration = initDuration(seconds=2)
  deciSecondDuration* = initDuration(milliseconds = 100)
  qtrsecondDuration* = initDuration(milliseconds = 250)

var
  client = newHttpClient()
  lastConnection = getTime().utc

proc resetHttpClient() =
  if (getTime().utc - lastConnection) > resetDuration:
    # Probably a new timeout. We have not yet experienced a long outage.
    # We may however be entering an extended outage.
    # Creating the new clients seems to use up lots of CPU.
    # I want to do that as little as possible.
    try:
      client.close()
    except:
      echo("Attempted to close clients. Probably do not exist.")
      echo("Current exception:  ", getCurrentExceptionMsg())
    client = newHttpClient(timeout=500)


# [TODO] procédure Ping à finir qui ne fonctionne pas.
proc ping_joplin*(token:string): Future[joplin_ping] {.async.} =
    
  var j_p: joplin_ping
  var client = newAsyncHttpClient()
  var url: string
  j_p.ping_status = false
  try:
    url = fmt"http://localhost:41184/ping?token={token}"
    var json = await client.getContent(url)
    j_p.ping_result.add(json)
    
    echo j_p.ping_result[0]

    if j_p.ping_result[0] == "JoplinClipperServer":
      j_p.ping_status = true

  except TimeoutError, IOError, OSError:
    # I naively think I would see this thrown or the plain except below.
    # But I almost never see an Error raised.
    echo("Current Exception: ", getCurrentException().name)
    echo("Current Exception Msg: ", getCurrentExceptionMsg())
    echo("Sleeping for 1 seconds at: ", getTime().utc)
    sleep(500)
    resetHttpClient()
    j_p.ping_status = false
  except:
    echo("Current Exception: ", getCurrentException().name)
    echo("Current Exception Msg: ", getCurrentExceptionMsg())
    echo("Sleeping for 1 seconds at: ", getTime().utc)
    j_p.ping_status = false  
  return j_p
    # parse jason
    #let joplin_notes_Json = parseJson(json)



proc get_joplin_notebooks*(token:string): Future[joplin_notebooks] {.async.} =
  
  # Variables
  var j_nb: joplin_notebooks
  var has_more: bool = true
  var page: int = 1
  var url: string
  var client = newAsyncHttpClient()
  var pingCheck: joplin_ping
  
  pingCheck = waitFor ping_joplin(token)

  # check the joplin status befor query 
  if pingCheck.ping_status:

    # make sure to check all pages 
    while has_more == true:
      
      # request joplin API for notebooks
      url = fmt"http://localhost:41184/folders?page={page}&token={token}"
      echo("URL notebooks : ", url)
      var json = await client.getContent(url)

      # parse jason
      let joplin_notebooks_Json = parseJson(json)

      # valider qu'il n'y a plus de page 
      if not joplin_notebooks_Json["has_more"].getBool:
        has_more = false 
      
      # store json info into an object
      var count: int = 1
      for nb in joplin_notebooks_Json["items"]:
        j_nb.id.add(nb["id"].getstr)
        j_nb.parent_id.add(nb["parent_id"].getstr)
        j_nb.title.add(nb["title"].getstr)
        count += 1
      
      # aller à la page suivante
      page += 1    

  return j_nb

proc get_joplin_notes*(token:string): Future[joplin_notes] {.async.} =
  
  # Variables
  var j_notes: joplin_notes
  var has_more: bool = true
  var page: int = 1
  var url: string
  var client = newAsyncHttpClient()
  var pingCheck: joplin_ping
  pingCheck = waitFor ping_joplin(token)

  # check the joplin status befor query 
  if pingCheck.ping_status:

    # make sure to check all pages 
    while has_more == true:
      
      # request joplin API for Notes
      url = fmt"http://localhost:41184/notes?page={page}&token={token}"
      echo("URL notes : ", url)
      var json = await client.getContent(url)

      # parse jason
      let joplin_notes_Json = parseJson(json)

      # valider qu'il n'y a plus de page 
      if not joplin_notes_Json["has_more"].getBool:
        has_more = false 
      
      # store json info into an object
      var count: int = 1
      for nb in joplin_notes_Json["items"]:
        j_notes.id.add(nb["id"].getstr)
        j_notes.parent_id.add(nb["parent_id"].getstr)
        j_notes.title.add(nb["title"].getstr)
        count += 1
      
      # aller à la page suivante
      page += 1    

  return j_notes


proc get_joplin_tags*(token:string): Future[joplin_tags] {.async.} =
  
  # Variables
  var j_tags: joplin_tags
  var has_more: bool = true
  var page: int = 1
  var url: string
  var client = newAsyncHttpClient()
  var pingCheck: joplin_ping
  pingCheck = waitFor ping_joplin(token)

  # check the joplin status befor query 
  if pingCheck.ping_status:

    # make sure to check all pages 
    while has_more == true:
      
      # request joplin API for notebooks
      url = fmt"http://localhost:41184/tags?page={page}&token={token}"
      echo("URL tags : ", url)
      var json = await client.getContent(url)

      # parse jason
      let joplin_tags_Json = parseJson(json)

      # valider qu'il n'y a plus de page 
      if not joplin_tags_Json["has_more"].getBool:
        has_more = false 
      
      # store json info into an object
      var count: int = 1
      for nb in joplin_tags_Json["items"]:
        j_tags.id.add(nb["id"].getstr)
        j_tags.parent_id.add(nb["parent_id"].getstr)
        j_tags.title.add(nb["title"].getstr)
        count += 1
      
      # aller à la page suivante
      page += 1    

  return j_tags



# proc get_joplin_tags_json*(token:string): Future[] {.async.} =

#   # url = fmt"http://localhost:41184/notes/{id}?fields=id,parent_id,title,body,created_time,updated_time,is_conflict,latitude,longitude,altitude,author,source_url,is_todo,todo_due,todo_completed,source,source_application,application_data,order,user_created_time,user_updated_time,encryption_cipher_text,encryption_applied,markup_language,is_shared,share_id,conflict_original_id,master_key_id&token={token}"

#   # url = fmt"http://localhost:41184/tags/{id}?fields=id,parent_id,title,created_time,updated_time,user_created_time,user_updated_time,is_shared&token={token}"

#   # http://localhost:41184/tags?token=e5f6644fbf6a97ddc55648dae72b11caecda6c6642d8ce0d3b20129b89b196385737eb908923542c3343649ebbf865b55bda031ab4c3a16edc7723ef2ad77d8f
  
#   # Variables
#   var j_tags: joplin_tags
#   var has_more: bool = true
#   var page: int = 1
#   var url: string
#   var client = newAsyncHttpClient()
#   var pingCheck: joplin_ping
#   pingCheck = waitFor ping_joplin(token)
  

#   # check the joplin status befor query 
#   if pingCheck.ping_status:

#     # make sure to check all pages 
#     while has_more == true:
      
#       # request joplin API for notebooks
#       url = fmt"http://localhost:41184/tags?page={page}&token={token}"
#       echo("URL tags : ", url)
#       var json = await client.getContent(url)

#       # parse jason
#       let joplin_tags_Json = parseJson(json)

#       # valider qu'il n'y a plus de page 
#       if not joplin_tags_Json["has_more"].getBool:
#         has_more = false 
      
#       # store json info into an object
#       var count: int = 1
#       for nb in joplin_tags_Json["items"]:
#         echo nb["id"].getstr
#         echo nb["parent_id"].getstr
#         echo nb["title"].getstr
#         count += 1
      
#       # aller à la page suivante
#       page += 1
  

