/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#include <precomp.h>
#include <s2_luidl/pe_struc.hxx>


// NOT FULLY DECLARED SERVICES
#include <ary/idl/i_gate.hxx>
#include <ary/idl/i_struct.hxx>
#include <ary/idl/ip_ce.hxx>
#include <ary/doc/d_oldidldocu.hxx>
#include <s2_luidl/tk_ident.hxx>
#include <s2_luidl/tk_punct.hxx>
#include <s2_luidl/tk_keyw.hxx>
#include <s2_luidl/pe_type2.hxx>
#include <s2_luidl/pe_selem.hxx>



namespace csi
{
namespace uidl
{


PE_Struct::PE_Struct()
    // :    aWork,
    //      pStati
{
    pStati = new S_Stati(*this);
}

void
PE_Struct::EstablishContacts( UnoIDL_PE *               io_pParentPE,
                              ary::Repository &			io_rRepository,
                              TokenProcessing_Result & 	o_rResult )
{
    UnoIDL_PE::EstablishContacts(io_pParentPE,io_rRepository,o_rResult);
    Work().pPE_Element->EstablishContacts(this,io_rRepository,o_rResult);
    Work().pPE_Type->EstablishContacts(this,io_rRepository,o_rResult);
}

PE_Struct::~PE_Struct()
{
}

void
PE_Struct::ProcessToken( const Token & i_rToken )
{
    i_rToken.Trigger(*Stati().pCurStatus);
}


void
PE_Struct::InitData()
{
    Work().InitData();
    Stati().pCurStatus = &Stati().aWaitForName;
}

void
PE_Struct::TransferData()
{
    if (NOT Work().bIsPreDeclaration)
    {
        csv_assert(! Work().sData_Name.empty());
        csv_assert(Work().nCurStruct.IsValid());
    }
    Stati().pCurStatus = &Stati().aNone;
}

void
PE_Struct::ReceiveData()
{
    Stati().pCurStatus->On_SubPE_Left();
}

PE_Struct::S_Work::S_Work()
    :   sData_Name(),
        sData_TemplateParam(),
        bIsPreDeclaration(false),
        nCurStruct(0),
        pPE_Element(0),
        nCurParsed_ElementRef(0),
        pPE_Type(0),
        nCurParsed_Base(0)

{
    pPE_Element = new PE_StructElement(nCurParsed_ElementRef,nCurStruct,sData_TemplateParam);
    pPE_Type = new PE_Type(nCurParsed_Base);
}

void
PE_Struct::S_Work::InitData()
{
    sData_Name.clear();
    sData_TemplateParam.clear();
    bIsPreDeclaration = false;
    nCurStruct = 0;
    nCurParsed_ElementRef = 0;
    nCurParsed_Base = 0;
}

void
PE_Struct::S_Work::Prepare_PE_QualifiedName()
{
    nCurParsed_ElementRef = 0;
}

void
PE_Struct::S_Work::Prepare_PE_Element()
{
    nCurParsed_Base = 0;
}

void
PE_Struct::S_Work::Data_Set_Name( const char * i_sName )
{
    sData_Name = i_sName;
}

void
PE_Struct::S_Work::Data_Set_TemplateParam( const char * i_sTemplateParam )
{
    sData_TemplateParam = i_sTemplateParam;
}

PE_Struct::S_Stati::S_Stati(PE_Struct & io_rStruct)
    :   aNone(io_rStruct),
        aWaitForName(io_rStruct),
        aGotName(io_rStruct),
        aWaitForTemplateParam(io_rStruct),
        aWaitForTemplateEnd(io_rStruct),
        aWaitForBase(io_rStruct),
        aGotBase(io_rStruct),
        aWaitForElement(io_rStruct),
        aWaitForFinish(io_rStruct),
        pCurStatus(0)
{
    pCurStatus = &aNone;
}


//***********************       Stati       ***************************//


UnoIDL_PE &
PE_Struct::PE_StructState::MyPE()
{
    return rStruct;
}


void
PE_Struct::State_WaitForName::Process_Identifier( const TokIdentifier & i_rToken )
{
    Work().Data_Set_Name(i_rToken.Text());
    MoveState( Stati().aGotName );
    SetResult(done,stay);
}

void
PE_Struct::State_GotName::Process_Punctuation( const TokPunctuation & i_rToken )
{
    if ( i_rToken.Id() != TokPunctuation::Semicolon )
    {
        switch (i_rToken.Id())
    	{
            case TokPunctuation::Colon:
                MoveState( Stati().aWaitForBase );
                SetResult(done,push_sure,Work().pPE_Type.Ptr());
                Work().Prepare_PE_QualifiedName();
            	break;
            case TokPunctuation::CurledBracketOpen:
                PE().store_Struct();
                MoveState( Stati().aWaitForElement );
                SetResult(done,stay);
            	break;
            case TokPunctuation::Lesser:
                MoveState( Stati().aWaitForTemplateParam );
                SetResult(done,stay);
            	break;
            default:
                SetResult(not_done,pop_failure);
        }   // end switch
    }
    else
    {
        Work().sData_Name.clear();
        SetResult(done,pop_success);
    }
}

void
PE_Struct::State_WaitForTemplateParam::Process_Identifier( const TokIdentifier & i_rToken )
{
    Work().Data_Set_TemplateParam(i_rToken.Text());
    MoveState( Stati().aWaitForTemplateEnd );
    SetResult(done,stay);
}

void
PE_Struct::State_WaitForTemplateEnd::Process_Punctuation( const TokPunctuation & )
{
    // Assume:  TokPunctuation::Greater
    MoveState( Stati().aGotName );
    SetResult(done,stay);
}

void
PE_Struct::State_WaitForBase::On_SubPE_Left()
{
    MoveState(Stati().aGotBase);
}

void
PE_Struct::State_GotBase::Process_Punctuation( const TokPunctuation & i_rToken )
{
    if ( i_rToken.Id() == TokPunctuation::CurledBracketOpen )
    {
        PE().store_Struct();
        MoveState( Stati().aWaitForElement );
        SetResult(done,stay);
    }
    else
    {
        SetResult(not_done,pop_failure);
    }
}

void
PE_Struct::State_WaitForElement::Process_Identifier( const TokIdentifier & )
{
    SetResult( not_done, push_sure, Work().pPE_Element.Ptr() );
    Work().Prepare_PE_Element();
}

void
PE_Struct::State_WaitForElement::Process_NameSeparator()
{
    SetResult( not_done, push_sure, Work().pPE_Element.Ptr());
    Work().Prepare_PE_Element();
}

void
PE_Struct::State_WaitForElement::Process_BuiltInType( const TokBuiltInType & )
{
    SetResult( not_done, push_sure, Work().pPE_Element.Ptr());
    Work().Prepare_PE_Element();
}

void
PE_Struct::State_WaitForElement::Process_TypeModifier(const TokTypeModifier & )
{
    SetResult( not_done, push_sure, Work().pPE_Element.Ptr());
    Work().Prepare_PE_Element();
}

void
PE_Struct::State_WaitForElement::Process_Punctuation( const TokPunctuation & i_rToken )
{
    if ( i_rToken.Id() == TokPunctuation::CurledBracketClose )
    {
        MoveState( Stati().aWaitForFinish );
        SetResult( done, stay );
    }
    else
    {
        SetResult( not_done, pop_failure );
    }
}

void
PE_Struct::State_WaitForFinish::Process_Punctuation( const TokPunctuation & i_rToken )
{
    if (i_rToken.Id() == TokPunctuation::Semicolon)
    {
        MoveState( Stati().aNone );
        SetResult( done, pop_success );
    }
    else
    {
        SetResult( not_done, pop_failure );
    }
}

void
PE_Struct::store_Struct()
{
    ary::idl::Struct &
        rCe = Gate().Ces().Store_Struct(
                        CurNamespace().CeId(),
                        Work().sData_Name,
                        Work().nCurParsed_Base,
                        Work().sData_TemplateParam );
    PassDocuAt(rCe);
    Work().nCurStruct = rCe.CeId();
}


}   // namespace uidl
}   // namespace csi
