/**
 * @file mark_question_colon.cpp
 *
 * @author  Guy Maurel
 * @license GPL v2+
 */

#include "mark_question_colon.h"

#include "chunk.h"
#include "combine_tools.h"
#include "log_levels.h"


/*
 * Issue #3558
 * will be called if a ? (CT_QUESTION) chunk is encountered
 * return the chunk colon if found or Chunk::NullChunkPtr
 * if a ; (CT_SEMI_COLON) chunk is found
 */
Chunk *search_for_colon(Chunk *pc_question)
{
   Chunk *pc2        = pc_question->GetNextNcNnl();
   bool  colon_found = false;

   LOG_FMT(LCOMBINE, "%s(%d): pc_question.orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
           __func__, __LINE__, pc_question->GetOrigLine(), pc_question->GetOrigCol(), pc_question->GetLevel(),
           pc_question->Text());

   // examine the next tokens, look for E2, E3, COLON, might be for a next CT_QUESTION
   while (pc2->IsNotNullChunk())
   {
      LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
              __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());

      if (  pc2->Is(CT_SEMICOLON)
         || (  pc2->Is(CT_PAREN_CLOSE)
            && (pc_question->GetLevel() == pc2->GetLevel() + 1))
         || pc2->Is(CT_COMMA))
      {
         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
         pc2->SetFlagBits(PCF_IN_CONDITIONAL);
         log_pcf_flags(LCOMBINE, pc2->GetFlags());

         if (colon_found)
         {
            LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                    __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
            pc_question->SetParent(pc2);   // back again

            LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                    __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
            return(pc2);
         }
         else
         {
            pc2->SetParent(pc_question);   // save the question token
            pc_question->SetParent(pc2);   // back again
         }
      }
      else if (pc2->Is(CT_COMMA))
      {
         // TODO: is it necessary?
      }
      else if (pc2->Is(CT_QUESTION))
      {
         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
         pc2 = search_for_colon(pc2);
         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
         continue;
      }
      else if (pc2->Is(CT_COND_COLON))
      {
         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());

         if (colon_found)
         {
            LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                    __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
            Chunk *pr = pc2->GetPrevNcNnl();
            return(pr);
         }
         else
         {
            pc2->SetParent(pc_question);              // save the question token
            pc_question->SetParent(pc2);              // back again
            colon_found = true;
         }

         if (pc2->Is(CT_COLON))
         {
            if (colon_found)
            {
               return(pc2);
            }
            else
            {
            }
         }
      }
      else if (pc2->Is(CT_COLON))
      {
         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());

         if (colon_found)
         {
            pc2->SetType(CT_COND_COLON);
            return(pc2);
         }
         else
         {
            // E2 found   orig line is 23, orig col is 3
            pc2->SetType(CT_COND_COLON);
            LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                    __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel(), pc2->Text());
            pc2->SetParent(pc_question);              // save the question token
            pc_question->SetParent(pc2);              // back again

            // look for E3
            colon_found = true;
         }
      }
      pc2 = pc2->GetNextNcNnl();
   }

   if (pc2->IsNotNullChunk())
   {
      LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '?'\n",
              __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel());
   }
   LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '?'\n",
           __func__, __LINE__, pc2->GetOrigLine(), pc2->GetOrigCol(), pc2->GetLevel());
   return(pc2);
} // search_for_colon


void mark_question_colon()
{
   LOG_FUNC_ENTRY();
   Chunk *pc = Chunk::GetHead();
   Chunk *pc_question;

   // Issue #3558
   while (pc->IsNotNullChunk())
   {
      LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
              __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
      log_pcf_flags(LCOMBINE, pc->GetFlags());

      if (  pc->Is(CT_QUESTION)
         && !language_is_set(LANG_JAVA))
      {
         pc_question = pc;
         // look for E2, COLON, E3...
         pc = search_for_colon(pc);

         LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                 __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());

         if (  pc->Is(CT_SEMICOLON)
            || (  pc->Is(CT_PAREN_CLOSE)
               && (pc_question->GetLevel() == pc->GetLevel() + 1))
            || pc->Is(CT_COMMA))
         {
            // set at the end of the question statement ...
            LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() is '%s'\n",
                    __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());
            // ... and go on
         }
      }
      pc = pc->GetNextNcNnl();
   }

   for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl())
   {
      LOG_FMT(LCOMBINE, "%s(%d): orig line is %zu, orig col is %zu, level is %zu, Text() '%s'\n",
              __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->GetLevel(), pc->Text());

      if (pc->Is(CT_QUESTION))
      {
         Chunk *from = pc;
         Chunk *to   = pc->GetParent();
         flag_series(from, to, PCF_IN_CONDITIONAL);
         pc = to;
      }
   }
} // mark_question_colon
