/*  $Id: struc_comm_field.hpp 638615 2021-10-02 09:47:34Z stakhovv $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
 *               National Center for Biotechnology Information
 *
 *  This software/database is a "United States Government Work" under the
 *  terms of the United States Copyright Act.  It was written as part of
 *  the author's official duties as a United States Government employee and
 *  thus cannot be copyrighted.  This software/database is freely available
 *  to the public for use. The National Library of Medicine and the U.S.
 *  Government have not placed any restriction on its use or reproduction.
 *
 *  Although all reasonable efforts have been taken to ensure the accuracy
 *  and reliability of the software and data,  the NLM and the U.S.
 *  Government do not and cannot warrant the performance or results that
 *  may be obtained by using this software or data. The NLM and the U.S.
 *  Government disclaim all warranties,  express or implied,  including
 *  warranties of performance,  merchantability or fitness for any particular
 *  purpose.
 *
 *  Please cite the author in any work or product based on this material.
 *
 * ===========================================================================
 *
 * Authors:  Colleen Bollin
 */
#ifndef _STRUC_COMM_FIELD_H_
#define _STRUC_COMM_FIELD_H_

#include <corelib/ncbistd.hpp>
#include <objects/general/User_object.hpp>
#include <objects/general/User_field.hpp>
#include <objects/valid/Comment_set.hpp>
#include <objects/valid/Comment_rule.hpp>

#include <objmgr/scope.hpp>

#include <objtools/edit/field_handler.hpp>
#include <objtools/edit/string_constraint.hpp>

BEGIN_NCBI_SCOPE
BEGIN_SCOPE(objects)

class CComment_set;
class CComment_rule;
class CField_rule;
class CField_set;


BEGIN_SCOPE(edit)


class NCBI_XOBJEDIT_EXPORT CStructuredCommentField : public CFieldHandler
{
public:

    CStructuredCommentField(const string& prefix, const string& field_name)
      : m_Prefix(prefix), m_FieldName(field_name)
    {
        CComment_rule::NormalizePrefix(m_Prefix);
    }

    vector<CConstRef<CObject>> GetObjects(CBioseq_Handle bsh) override;
    vector<CConstRef<CObject>> GetObjects(CSeq_entry_Handle seh,
                                          const string& constraint_field,
                                          CRef<CStringConstraint> string_constraint) override;
    vector<CRef<CApplyObject>> GetApplyObjects(CBioseq_Handle bsh) override;
    vector<CConstRef<CObject>> GetRelatedObjects(const CObject& object, CRef<CScope> scope) override;
    vector<CConstRef<CObject>> GetRelatedObjects(const CApplyObject& object) override;

    bool IsEmpty(const CObject& object) const override;
    string GetVal(const CObject& object) override;
    vector<string> GetVals(const CObject& object) override;
    void ClearVal(CObject& object) override;

    CSeqFeatData::ESubtype GetFeatureSubtype() override { return CSeqFeatData::eSubtype_bad; }
    CSeqdesc::E_Choice GetDescriptorSubtype() override { return CSeqdesc::e_User; }
    void SetConstraint(const string& field_name, CConstRef<CStringConstraint> string_constraint) override;
    bool AllowMultipleValues() override { return false; }
    bool SetVal(CObject& object,
                const string& newValue,
                EExistingText existing_text = eExistingText_replace_old) override;
    bool SetVal(CUser_field& field, const string& newValue, EExistingText existing_text);

    virtual string GetLabel() const { return m_Prefix + " " + m_FieldName; }
    bool IsStructuredCommentForThisField(const CUser_object& user) const;
    static CRef<CUser_object> MakeUserObject(const string& prefix);
    static bool IsValid(const CUser_object& obj, const string& desired_prefix);
    static void ReorderFields(CUser_object& obj);

protected:
    string m_Prefix;
    string m_FieldName;
    string m_ConstraintFieldName;
    CRef<CStringConstraint> m_StringConstraint;

    void x_InsertFieldAtCorrectPosition(CUser_object& user, CRef<CUser_field> field);
};


class NCBI_XOBJEDIT_EXPORT CGenomeAssemblyComment
{
public:
    CGenomeAssemblyComment();
    CGenomeAssemblyComment(CUser_object& user);
    ~CGenomeAssemblyComment() {};
    static CRef<CUser_object> MakeEmptyUserObject();
    static void SetAssemblyMethod(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetAssemblyMethodProgram(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetAssemblyMethodVersion(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetGenomeCoverage(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetSequencingTechnology(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetExpectedFinalVersion(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetReferenceGuidedAssembly(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);
    static void SetSingleCellAmplification(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old);

    static string GetAssemblyMethod(const CUser_object& obj);
    static string GetAssemblyMethodProgram(const CUser_object& obj);
    static string GetAssemblyMethodVersion(const CUser_object& obj);
    static string GetGenomeCoverage(const CUser_object& obj);
    static string GetSequencingTechnology(const CUser_object& obj);
    static string GetExpectedFinalVersion(const CUser_object& obj);
    static string GetReferenceGuidedAssembly(const CUser_object& obj);
    static string GetSingleCellAmplification(const CUser_object& obj);

    CGenomeAssemblyComment& SetAssemblyMethod(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetAssemblyMethodProgram(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetAssemblyMethodVersion(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetGenomeCoverage(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetSequencingTechnology(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetExpectedFinalVersion(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetReferenceGuidedAssembly(string val, EExistingText existing_text = eExistingText_replace_old);
    CGenomeAssemblyComment& SetSingleCellAmplification(string val, EExistingText existing_text = eExistingText_replace_old);
    CRef<CUser_object> MakeUserObject();

    static bool IsValid(const CUser_object& obj);

protected:
    CRef<CUser_object> m_User;

    static void x_GetAssemblyMethodProgramAndVersion(string val, string& program, string& version);
    static string x_GetAssemblyMethodFromProgramAndVersion(const string& program, const string& version);
};


class NCBI_XOBJEDIT_EXPORT CANIComment
{
public:
    CANIComment();
    CANIComment(CUser_object& user);
    ~CANIComment() {};
    static CRef<CUser_object> MakeEmptyUserObject();

#define ANI_STRING_FIELD(Fieldname) \
    static void Set##Fieldname(CUser_object& obj, string val, EExistingText existing_text = eExistingText_replace_old); \
    static string Get##Fieldname(const CUser_object& obj); \
    CANIComment& Set##Fieldname(string val, EExistingText existing_text = eExistingText_replace_old); \
    string Get##Fieldname() { return Get##Fieldname(*m_User); }

    ANI_STRING_FIELD(ThisGenome)
    ANI_STRING_FIELD(CurrentName)
    ANI_STRING_FIELD(PreviousName)
    ANI_STRING_FIELD(DateUpdated)
    ANI_STRING_FIELD(AnalysisType)
    ANI_STRING_FIELD(Analysis1)
    ANI_STRING_FIELD(A1Genome)
    ANI_STRING_FIELD(A1Name)
    ANI_STRING_FIELD(A1ANI)
    ANI_STRING_FIELD(A1QueryCoverage)
    ANI_STRING_FIELD(A1SubjectCoverage)
    ANI_STRING_FIELD(Analysis2)
    ANI_STRING_FIELD(A2Genome)
    ANI_STRING_FIELD(A2Name)
    ANI_STRING_FIELD(A2ANI)
    ANI_STRING_FIELD(A2QueryCoverage)
    ANI_STRING_FIELD(A2SubjectCoverage)

    CRef<CUser_object> MakeUserObject();

    static bool IsValid(const CUser_object& obj);

protected:
    CRef<CUser_object> m_User;
};


END_SCOPE(edit)
END_SCOPE(objects)
END_NCBI_SCOPE

#endif
// _STRUC_COMM_FIELD_H_

