-- Autogenerated with DRAKON Editor 1.33
local table = table
local string = string
local pairs = pairs
local ipairs = ipairs
local type = type
local box = box
local tostring = tostring
local tonumber = tonumber
local print = print
local math = math
local os = os
local error = error
local global_cfg = global_cfg
local globs = globs
local pcall = pcall

local clock = require("clock")
local log = require("log")
local digest = require("digest")
local fiber = require("fiber")
local utils = require("utils")
local fun = require("fun")
local json = require("json")

local utf8 = require("lua-utf8")

local folders = box.space.folders
local items = box.space.items
local spaces = box.space.spaces
local usettings = box.space.usettings
local recent = box.space.recent
local rights = box.space.rights
local trash = box.space.trash
local folder_tree = box.space.folder_tree
local folder_props = box.space.folder_props

local users = box.space.users
local sessions = box.space.sessions
local creds = box.space.creds
local usecrets = box.space.usecrets
local user_props = box.space.user_props

local payments = box.space.payments
local agreements = box.space.agreements
local scheduled = box.space.scheduled
local transactions = box.space.transactions
local licenses = box.space.licenses
local coupons = box.space.coupons

local search_yield = 0.02
local current_version = 20180619

local module = {}
module.transactions = {}

setfenv(1, {}) 

function agreement_delete(id)
    agreements:delete(
        {id}
    )
end

function agreement_get(id)
    local row
    row = agreements:get(id)
    if row then
        return row[3], row[2]
    else
        return nil
    end
end

function agreement_get_by_order_ref(order_ref)
    local found, index
    index = agreements.index.by_order
    found = index:select(
        order_ref,
        {iterator = "EQ"}
    )
    return found
end

function agreement_insert(id, order_ref, data)
    agreements:insert {
    	id,
    	order_ref,
    	data
    }
end

function agreement_update(agreement_id, order_ref, data)
    agreements:replace {
    	agreement_id,
    	order_ref,
    	data
    }
end

function agreement_update_data(agreement_id, agreement)
    agreements:update(
    	agreement_id,
    	{{"=", 3, agreement }}
    )
end

function agreement_update_order(agreement_id, order_ref)
    utils.update2(
    	agreements,
    	agreement_id,
    	order_ref
    )
end

function begin()
    local id
    id = get_fiber_id()
    if module.transactions[id] then
        error("Already in transaction")
    else
        module.transactions[id] = true
        box.begin()
    end
end

function clean_up()
    local id
    id = get_fiber_id()
    if module.transactions[id] then
        box.rollback()
        module.transactions[id] = nil
    end
end

function commit()
    local id
    id = get_fiber_id()
    if module.transactions[id] then
        box.commit()
        module.transactions[id] = nil
    else
        error("Not in transaction")
    end
end

function coupon_get(code)
    local data, row
    row = coupons:get(code)
    if row then
        data = row[2]
        return data
    else
        return nil
    end
end

function coupon_insert(code, data)
    coupons:insert {
    	code,
    	data
    }
end

function coupon_update(code, data)
    coupons:replace {
    	code,
    	data
    }
end

function cred_delete(user_id)
    creds:delete{user_id}
end

function cred_get(user_id)
    local row
    row = creds:get(user_id)
    if row then
        return row[2]
    else
        return nil
    end
end

function cred_upsert(user_id, cred)
    creds:replace{user_id, cred}
end

function folder_delete(space_id, folder_id)
    folders:delete(
        {space_id, folder_id}
    )
end

function folder_get(space_id, folder_id)
    local folder
    folder = folders:get(
        {space_id, folder_id}
    )
    if folder then
        local fdata = folder[3]
        return fdata
    else
        return nil
    end
end

function folder_get_all()
    return folders:select()
end

function folder_get_by_space(space_id)
    return folders:select(
        {space_id}
    )
end

function folder_insert(space_id, folder_id, fdata)
    folders:insert(
        {space_id, folder_id, fdata}
    )
end

function folder_props_delete(space_id, folder_id)
    local props
    props = folder_props_get_by_folder(
        space_id,
        folder_id
    )
    for _, prop in ipairs(props) do
        folder_props:delete(
            {prop[1], prop[2], prop[3]}
        )
    end
end

function folder_props_get(space_id, folder_id, prop)
    local row
    row = folder_props:get(
        {space_id, folder_id, prop}
    )
    if row then
        return row[4]
    else
        return nil
    end
end

function folder_props_get_by_folder(space_id, folder_id)
    return folder_props:select(
        {space_id, folder_id}
    )
end

function folder_props_insert(space_id, folder_id, prop, value)
    folder_props:insert(
        {space_id, folder_id, prop, value}
    )
end

function folder_tree_delete(space_id, folder_id)
    folder_tree:delete {
    	space_id,
    	folder_id
    }
end

function folder_tree_get(space_id, folder_id)
    local row
    row = folder_tree:get {
    	space_id,
    	folder_id
    }
    if row then
        return row[3]
    else
        return nil
    end
end

function folder_tree_get_by_parent(space_id, parent_id)
    return folder_tree.index.by_parent:select {
    	space_id,
    	parent_id
    }
end

function folder_tree_get_by_space(space_id, folder_id)
    return folder_tree:select{space_id}
end

function folder_tree_upsert(space_id, folder_id, parent_id)
    folder_tree:replace {
    	space_id,
    	folder_id,
    	parent_id,
    	{}
    }
end

function folder_update(space_id, folder_id, fdata)
    utils.update3(
        folders,
        space_id,
        folder_id,
        fdata
    )
end

function get_fiber_id()
    return fiber.self():id()
end

function invoke_no_throw(action, description)
    local ok, result = pcall(action)
    if ok then
        return result
    else
        log.error(
          "error: "
          .. tostring(description)
          .. tostring(result)
        )
        clean_up()
        return nil
    end
end

function item_count()
    return items:count()
end

function item_delete(space_id, folder_id, item_id)
    items:delete(
        {space_id, folder_id, item_id}
    )
end

function item_get(space_id, folder_id, item_id)
    local item
    item = items:get{
    	space_id,
    	folder_id,
    	item_id
    }
    if item then
        return item[4]
    else
        return nil
    end
end

function item_get_by_folder(space_id, folder_id)
    return items:select(
        {space_id, folder_id}
    )
end

function item_insert(space_id, folder_id, item_id, idata)
    items:insert(
        {space_id, folder_id, item_id, idata}
    )
end

function item_update(space_id, folder_id, item_id, idata)
    utils.update4(
    	items,
    	space_id,
    	folder_id,
    	item_id,
    	idata
    )
end

function license_delete(id)
    licenses:delete(id)
end

function license_get(id)
    local data, row
    row = licenses:get(id)
    if row then
        data = row[2]
        return data
    else
        return nil
    end
end

function license_insert(data)
    local id, row
    row = licenses:auto_increment {
    	data
    }
    id = row[1]
    return id
end

function license_update(id, data)
    licenses:replace {
    	id,
    	data
    }
end

function payment_delete(payment_id)
    payments:delete(
        {payment_id}
    )
end

function payment_get_by_user(user_id)
    return payments.index.by_user:select(
        user_id
    )
end

function payment_insert(user_id, payment)
    payments:auto_increment {user_id, payment}
end

function recent_by_space(space_id)
    return recent:select(
        {space_id}
    )
end

function recent_delete(space_id, folder_id, user_id)
    recent:delete {
    	space_id,
    	folder_id,
    	user_id
    }
end

function recent_get_by_folder(space_id, folder_id)
    return recent:select(
        {space_id, folder_id}
    )
end

function recent_get_by_user(user_id)
    return recent.index.by_user:select{user_id}
end

function recent_upsert(space_id, folder_id, user_id, data)
    utils.write4(
    	recent,
    	space_id,
    	folder_id,
    	user_id,
    	data
    )
end

function rights_delete(space_id, user_id, access)
    rights:delete(
        {space_id, user_id, access}
    )
end

function rights_delete_by_space(space_id)
    local access, rows, user_id
    rows = rights_get_by_space(space_id)
    for _, row in ipairs(rows) do
        user_id = row[2]
        access = row[3]
        rights:delete(
            {space_id, user_id, access}
        )
    end
end

function rights_delete_by_user(user_id)
    local access, rows, space_id
    rows = rights_get_by_user(user_id)
    for _, row in ipairs(rows) do
        space_id = row[1]
        access = row[3]
        rights:delete(
            {space_id, user_id, access}
        )
    end
end

function rights_get_by_space(space_id)
    return rights:select {space_id}
end

function rights_get_by_space_user(space_id, user_id)
    return rights:select {space_id, user_id}
end

function rights_get_by_user(user_id)
    return rights.index.by_user:select(user_id)
end

function rights_insert(space_id, user_id, access, data)
    rights:insert(
        {space_id, user_id, access, data}
    )
end

function rollback()
    local id
    id = get_fiber_id()
    if module.transactions[id] then
        box.rollback()
        module.transactions[id] = nil
    else
        error("Not in transaction")
    end
end

function run_in_fiber(action, description)
    local safe_action = function()
    	invoke_no_throw(action, description)
    end
    fiber.create(safe_action)
end

function scheduled_delete(agreement_id)
    scheduled:delete(agreement_id)
end

function scheduled_get(agreement_id)
    local srow = scheduled:get(agreement_id)
    if srow then
        return srow[2]
    else
        return nil
    end
end

function scheduled_get_all()
    return scheduled:select()
end

function scheduled_upsert(agreement_id, data)
    scheduled:replace {
    	agreement_id,
    	data
    }
end

function session_count()
    return sessions:count()
end

function session_delete(session_id)
    sessions:delete(
        {session_id}
    )
end

function session_get(session_id)
    return sessions:get(
        {session_id}
    )
end

function session_get_by_user(user_id)
    return sessions.index.by_user:select(user_id)
end

function session_insert(session_id, user_id, sdata)
    sessions:insert(
        {session_id, user_id, sdata}
    )
end

function session_update(session_id, user_id, sdata)
    sessions:replace{session_id, user_id, sdata}
end

function space_count()
    return spaces:count()
end

function space_delete(space_id)
    spaces:delete(
        {space_id}
    )
end

function space_get(space_id)
    local space
    space = spaces:get(
        {space_id}
    )
    if space then
        return space[2]
    else
        return nil
    end
end

function space_get_all()
    return spaces:select()
end

function space_insert(space_id, sdata)
    spaces:insert{ space_id, sdata }
end

function space_update(space_id, sdata)
    utils.update2(
        spaces,
        space_id,
        sdata
    )
end

function stats_get(req, session, headers)
    local diagrams, users
    local dia_count = 0
    for key, tuple in folders:pairs() do
        local fdata = tuple[3]
        if fdata.type == "folder" then
            
        else
            dia_count = dia_count + 1
        end
    end
    local rdata = {
    	users = users:count(),
    	diagrams = dia_count
    }
    return rdata
end

function transaction_delete(id)
    transactions:delete(id)
end

function transaction_get(id)
    local data, row, user_id
    row = transactions:get(id)
    if row then
        id = row[1]
        user_id = row[2]
        data = row[3]
        data.user_id = user_id
        data.id = id
        return data
    else
        return nil
    end
end

function transaction_get_by_user(user_id)
    return transactions.index.by_user:select(user_id)
end

function transaction_insert(id, user_id, tdata)
    transactions:insert {
    	id,
    	user_id,
    	tdata
    }
end

function transaction_update(id, user_id, tdata)
    transactions:replace {
    	id,
    	user_id,
    	tdata
    }
end

function trash_delete(space_id, folder_id)
    trash:delete(
        {space_id, folder_id}
    )
end

function trash_get_all()
    return trash:select()
end

function trash_get_by_space(space_id)
    return trash:select(
        {space_id}
    )
end

function trash_insert(space_id, folder_id)
    trash:insert(
        {space_id, folder_id, {}}
    )
end

function usecret_delete(user_id)
    usecrets:delete{user_id}
end

function usecret_get(user_id)
    local row
    row = usecrets:get(user_id)
    if row then
        return row[2]
    else
        return nil
    end
end

function usecret_upsert(user_id, cred)
    usecrets:replace{user_id, cred}
end

function user_count()
    return users:count()
end

function user_delete(user_id)
    users:delete { user_id }
end

function user_get(user_id)
    return users:get(
        {user_id}
    )
end

function user_get_all()
    return users:select()
end

function user_get_by_email(email)
    return users.index.by_email:get(email)
end

function user_get_email(user_id)
    local user
    user = users:get(
        {user_id}
    )
    if user then
        return user[2]
    else
        return nil
    end
end

function user_insert(id, email, data)
    users:insert {id, email, data}
end

function user_props_delete(user_id)
    local props
    props = user_props_get_by_user(user_id)
    for _, prop in ipairs(props) do
        user_props:delete(
            {prop[1], prop[2]}
        )
    end
end

function user_props_get_by_user(user_id)
    return user_props:select(
        {user_id}
    )
end

function user_props_upsert(user_id, prop, value)
    user_props:replace(
        {user_id, prop, value}
    )
end

function user_update(id, email, data)
    users:replace {id, email, data}
end


return {
folder_get = folder_get,
folder_insert = folder_insert,
folder_delete = folder_delete,
folder_get_by_space = folder_get_by_space,
folder_update = folder_update,
folder_get_all = folder_get_all,

item_get = item_get,
item_update = item_update,
item_insert = item_insert,
item_delete = item_delete,
item_get_by_folder = item_get_by_folder,

space_get = space_get,
space_insert = space_insert,
space_delete = space_delete,
space_get_all = space_get_all,
space_update = space_update,


recent_upsert = recent_upsert,
recent_get_by_folder = recent_get_by_folder,
recent_get_by_user = recent_get_by_user,
recent_delete = recent_delete,

begin = begin,
commit = commit,
rollback = rollback,
clean_up = clean_up,

user_get_email = user_get_email,
user_get = user_get,
user_insert = user_insert,
user_delete = user_delete,
user_get_by_email = user_get_by_email,
user_update = user_update,
user_get_all = user_get_all,

session_get_by_user = session_get_by_user,
session_get = session_get,
session_delete = session_delete,
session_insert = session_insert,
session_update = session_update,

usecret_get = usecret_get,
usecret_upsert = usecret_upsert,
usecret_delete = usecret_delete,

cred_get = cred_get,
cred_upsert = cred_upsert,
cred_delete = cred_delete,

stats_get = stats_get,

payment_get_by_user = payment_get_by_user,
payment_delete = payment_delete,
payment_insert = payment_insert,

agreement_get = agreement_get,
agreement_delete = agreement_delete,
agreement_get_by_order_ref = agreement_get_by_order_ref,
agreement_insert = agreement_insert,
agreement_update = agreement_update,
agreement_update_order = agreement_update_order,
agreement_update_data = agreement_update_data,

transaction_get = transaction_get,
transaction_insert = transaction_insert,
transaction_get_by_user = transaction_get_by_user,
transaction_update = transaction_update,
transaction_delete = transaction_delete,

license_insert = license_insert,
license_delete = license_delete,
license_get = license_get,
license_update = license_update,

coupon_insert = coupon_insert,
coupon_get = coupon_get,
coupon_update = coupon_update,

scheduled_delete = scheduled_delete,
scheduled_get = scheduled_get,
scheduled_upsert = scheduled_upsert,
scheduled_get_all = scheduled_get_all,

item_count = item_count,
space_count = space_count,
user_count = user_count,
session_count = session_count,

rights_insert = rights_insert,
rights_delete = rights_delete,
rights_get_by_space = rights_get_by_space,
rights_get_by_user = rights_get_by_user,
rights_get_by_space_user = rights_get_by_space_user,
rights_delete_by_space = rights_delete_by_space,
rights_delete_by_user = rights_delete_by_user,

trash_get_by_space = trash_get_by_space,
trash_insert = trash_insert,
trash_delete = trash_delete,
trash_get_all = trash_get_all,

folder_tree_upsert = folder_tree_upsert,
folder_tree_delete = folder_tree_delete,
folder_tree_get_by_parent = folder_tree_get_by_parent,
folder_tree_get = folder_tree_get,

invoke_no_throw = invoke_no_throw,
run_in_fiber = run_in_fiber,

folder_props_insert = folder_props_insert,
folder_props_delete = folder_props_delete,
folder_props_get_by_folder = folder_props_get_by_folder,
folder_props_get = folder_props_get,

user_props_upsert = user_props_upsert,
user_props_delete = user_props_delete,
user_props_get_by_user = user_props_get_by_user,

recent_by_space = recent_by_space,
folder_tree_get_by_space = folder_tree_get_by_space
}
