/*
 * app_cone.cpp
 *
 *  Created on: Aug 14, 2025
 *      Author: anders
 */

#include <iostream>
#include <fstream>
#include <stdlib.h>
#include "parser.h"
#include "printer.h"
#include "gfanapplication.h"
#include "gfanlib_tableau.h"
#include "gfanlib_circuittableinteger.h"
#include "log.h"

using namespace gfan;


class ReplaceApplication : public GFanApplication
{
	StringOption optionPattern;
	StringOption optionReplacement;
public:
  bool includeInDefaultInstallation()
  {
    return true;
  }
  const char *helpText()
  {
    return "This program can replace multi-line strings in a stdin stream and write the new stream to stdout. The way to pass line breaks in arguments in bash is to do $'\\n' as an escape sequence for a newline.\n";
  }
  ReplaceApplication():
	  optionPattern("-p","Specify pattern.",""),
	  optionReplacement("-r","Specify replacement.","")
  {
	  registerOptions();
  }

  const char *name()
  {
    return "_replace";
  }

  void inc(int &a, int bound)
  {
	  a++;
	  if(a>=bound)a-=bound;
  }

  int main()
  {
//	  string pattern="{\n{";
//	  string replacement="{";

	  string pattern=optionPattern.getValue();
	  string replacement=optionReplacement.getValue();

	  log1 debug<<"Pattern length:"<<(int)pattern.size()<<" Replacement length:"<<(int)replacement.size()<<"\n";

	  assert(pattern.size());

	  int n=pattern.size()+4096;
	  {
		  char buffer[n];
		  int bufferstart=0;
		  int bufferend=0;
		  int bufferused=0;
		  do
		  {
			  while(!cin.eof() && bufferused<n)
			  {
				  if(!cin.eof())
				  {
				  if(1)
				  {
					  int toRead=n-bufferused;
					  if(bufferend+toRead>n)toRead=n-bufferend;
					  cin.read(&(buffer[bufferend]),toRead);
					  int r=cin.gcount();
					  bufferend+=r;
					  if(bufferend>=n)bufferend-=n;
					  bufferused+=r;
				  }
				  else
				  {
					  cin.get(buffer[bufferend]);
					  inc(bufferend,n);
					  bufferused++;
				  }
				  }
			  }

			  while(pattern.size()<=bufferused)
			  {
				  bool match=true;
				  int i=bufferstart;
				  for(auto c:pattern)
				  {
					  if(buffer[i]!=c)
					  {
						  match=false;
						  break;
					  }
					  inc(i,n);
				  }
				  if(!match)
				  {
					  cout.put(buffer[bufferstart]);
					  inc(bufferstart,n);
					  bufferused--;
				  }
				  else
				  {
					  cout<<replacement;
					  for(auto c:pattern)
					  {
						  inc(bufferstart,n);
						  bufferused--;
					  }
				  }
			  }

		  }
		  while(!cin.eof() || bufferused>=pattern.size());

		  while(bufferused)
		  {
			  cout.put(buffer[bufferstart]);
			  inc(bufferstart,n);
			  bufferused--;
		  }
	  }



/*	  while(!cin.eof())
	  {
		  char c;
		  cin.get(c);
		  cout.put(c);
	  }*/
	  return 0;
  }
};

static ReplaceApplication theApplication;

