/******************************************************************************
 *
 * Copyright (c) 2017, the Perspective Authors.
 *
 * This file is part of the Perspective library, distributed under the terms of
 * the Apache License 2.0.  The full license can be found in the LICENSE file.
 *
 */

#pragma once
#include <perspective/first.h>
#include <perspective/base.h>
#include <perspective/context_base.h>
#include <perspective/sort_specification.h>

#include <perspective/sym_table.h>
#include <perspective/traversal.h>
#include <perspective/flat_traversal.h>
#include <perspective/data_table.h>
#include <perspective/expression_tables.h>
#include <perspective/expression_vocab.h>
#include <perspective/regex.h>
#include <tsl/hopscotch_set.h>

namespace perspective {

class t_data_table;

class PERSPECTIVE_EXPORT t_ctx0 : public t_ctxbase<t_ctx0> {
public:
    t_ctx0();

    t_ctx0(const t_schema& schema, const t_config& config);

    ~t_ctx0();
#include <perspective/context_common_decls.h>

    t_tscalar get_column_name(t_index idx);

    std::vector<std::string> get_column_names() const;

    const tsl::hopscotch_set<t_tscalar>& get_delta_pkeys() const;

    void sort_by();
    std::vector<t_sortspec> get_sort_by() const;

    std::pair<t_tscalar, t_tscalar> get_min_max(
        const std::string& colname) const;

    using t_ctxbase<t_ctx0>::get_data;

protected:
    std::vector<t_tscalar> get_all_pkeys(
        const std::vector<std::pair<t_uindex, t_uindex>>& cells) const;

    /**
     * @brief During a call to `notify` when the master table is being updated
     * with data for the first time (prev, curr, and transitions tables are
     * empty), take all added rows in the traversal and store them in
     * `m_deltas`.
     *
     * @param flattened
     */
    void calc_step_delta(const t_data_table& flattened);

    /**
     * @brief During a call to `notify` when the master table has data,
     * calculate the deltas - both changed and added cells, and write them
     * to `m_deltas`.
     *
     * @param flattened
     * @param prev
     * @param curr
     * @param transitions
     */
    void calc_step_delta(const t_data_table& flattened,
        const t_data_table& prev, const t_data_table& curr,
        const t_data_table& transitions);

    void add_delta_pkey(t_tscalar pkey);

    /**
     * @brief Read the specified column using the gnode's mapping - if the
     * column is an expression column, uses the expression master table,
     * otherwise use the gstate master table.
     *
     * @param colname
     * @param pkeys
     * @param out_data
     */
    void read_column_from_gstate(const std::string& colname,
        const std::vector<t_tscalar>& pkeys,
        std::vector<t_tscalar>& out_data) const;

private:
    std::shared_ptr<t_ftrav> m_traversal;
    std::shared_ptr<t_zcdeltas> m_deltas;
    tsl::hopscotch_set<t_tscalar> m_delta_pkeys;
    std::shared_ptr<t_expression_tables> m_expression_tables;
    t_symtable m_symtable;
    bool m_has_delta;
};

} // end namespace perspective
