#include "GuiCppGen.h"
namespace
 
{
	
namespace
 
	{
		
using
 namespace
 collections
;
		
using
 namespace
 stream
;
		
using
 namespace
 filesystem
;
		
using
 namespace
 parsing
;
		
using
 namespace
 workflow
;
		
using
 namespace
 workflow
::
cppcodegen
;
		
bool
 (
			
collections
::
<
>& 
,
			
const
 filesystem
::
& 
)
		{
			
<
> 
;
			
::
(
, 
output
);
			
return
 (
).
(
output
, 
true
, 
::
);
		}
		
<
> 
(
			
<
> 
,
			
IGuiResourcePrecompileCallback
* 
,
			
collections
::
<
>& 
)
		{
			
auto
  = 
(
, 
);
			
return
 precompiledFolder
;
		}
		
<
GuiInstanceCompiledWorkflow
> 
(
			
<
> 
,
			
const
 & 
,
			
const
 filesystem
::
& 
)
		{
			
if
 (
)
			{
				
if
 (
auto
  = 
(
).
<
GuiInstanceCompiledWorkflow
>())
				{
					
 ;
					
if
 (
compiled
)
					{
						
auto
& 
 = 
compiled
;
						FOREACH_INDEXER(WString, code, codeIndex, codes)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
>& 
 = ::
vl
::
collections
::
(
codes
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
if
(
bool
 =
true
) 
for
(
  = 
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
 ;
__foreach_iterator__
.
(
code
);
codeIndex
++)
 
						{
							
text
 += 
L"================================("
 + 
(
codeIndex
 + 
1
) + 
L"/"
 + 
(
codes
.
()) + 
L")================================\r\n"
;
							
text
 += 
code
 + 
L"\r\n"
;
						}
					}
					
else
					{
						FOREACH_INDEXER(GuiInstanceCompiledWorkflow::ModuleRecord, moduleRecord, codeIndex, compiled->modules)
						if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
GuiInstanceCompiledWorkflow
::
>& 
 = ::
vl
::
collections
::
(
compiled
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
if
(
bool
 =
true
) 
for
(
  = 
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
GuiInstanceCompiledWorkflow
::
 ;
__foreach_iterator__
.
(
moduleRecord
);
codeIndex
++)
 
						{
							
  = 
([&](
& 
)
							{
								
(
moduleRecord
.
, 
L""
, 
writer
);
							});
							
text
 += 
L"================================("
 + 
(
codeIndex
 + 
1
) + 
L"/"
 + 
(
compiled
.
()) + 
L")================================\r\n"
;
							
text
 += 
code
 + 
L"\r\n"
;
						}
					}
					
if
 (
(
).
(
text
))
					{
						
return
 compiled
;
					}
				}
			}
			
return
 nullptr
;
		}
		
<
workflow
::
cppcodegen
::
> 
(
			
<
> 
,
			
<
GuiInstanceCompiledWorkflow
> 
,
			
<
workflow
::
cppcodegen
::
> 
,
			
const
 filesystem
::
& 
,
			
collections
::
<
>& 
)
		{
			
auto
  = 
(
, 
.
());
			
if
 (
.
() > 
0
)
			{
				FOREACH(Ptr<ParsingError>, error, compiled->metadata->errors)
				if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
<
>>& 
 = ::
vl
::
collections
::
(
);
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
<
> 
;
__foreach_iterator__
.
(
error
);)
 
				{
					
.
(
({ {
} }, 
error
));
				}
				
return
 nullptr
;
			}
			FOREACH_INDEXER(WString, fileName, index, output->cppFiles.Keys())
			if
(
bool
 =
true
) 
for
(
const
 ::
vl
::
collections
::
<
>& 
 = ::
vl
::
collections
::
(
output
.
());
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
if
(
bool
 =
true
) 
for
(
  = 
0
;
__scope_variable_flag__
;
__scope_variable_flag__
=
false
) 
for
(
 ;
__foreach_iterator__
.
(
fileName
);
index
++)
 
			{
				
  = 
output
.
()
index
];
				
 (
  fileName
);
				
if
 (
file
.
())
				{
					
 ;
					
::
 ;
					
bool
 ;
					
file
.
ReadAllTextWithEncodingTesting
(
inputText
, 
inputEncoding
, 
inputBom
);
					
code
  (
inputText
, 
code
);
				}
				
if
 (
file
.
())
				{
					
 ;
					
::
 ;
					
bool
 ;
					
file
.
ReadAllTextWithEncodingTesting
(
inputText
, 
inputEncoding
, 
inputBom
);
					
if
 (
inputText
 == 
code
)
					{
						
continue
;
					}
				}
				
file
.
(
code
, 
true
, 
::
);
			}
			
return
 output
;
		}
		
bool
 (
			
<
> 
,
			
bool
 ,
			
bool
 includeAssemblyInResource
,
			
<
filesystem
::
> 
,
			
<
filesystem
::
> 
)
		{
			
auto
  = 
(
L"Precompiled"
);
			
auto
  = 
precompiled
->GetFolder(
L"Workflow"
);
			
if
 (
)
			{
				
 (
.
().
(), 
::
);
				
if
 (!
fileStream
.
()) 
return
 false
;
				
if
 (!
includeAssemblyInResource
) 
precompiled
->RemoveFolder(
L"Workflow"
);
				
if
 (
)
				{
					
 ;
					
 (
fileStream
, 
encoder
);
					
(
encoderStream
);
				}
				
else
				{
					
(
fileStream
);
				}
				
if
 (!
includeAssemblyInResource
) 
precompiled
->AddFolder(
L"Workflow"
, 
folder
);
			}
			
if
 (
)
			{
				
if
 (
auto
  = 
folder
->GetItem(
L"InstanceClass"
))
				{
					
if
 (
auto
  = 
item
->GetContent().Cast<
GuiInstanceCompiledWorkflow
>())
					{
						
if
 (
compiled
->assembly)
						{
							
 (
.
().
(), 
::
);
							
if
 (!
fileStream
.
()) 
return
 false
;
							
compiled
->assembly->Serialize(
fileStream
);
						}
					}
				}
			}
			
return
 true
;
		}
		
void
 (
& 
, 
bool
 , 
const
 & 
, 
const
 & 
, 
& 
)
		{
			
 ;
			
.
(
0
);
			
if
 (
)
			{
				
(
, 
compressedStream
);
			}
			
else
			{
				
(
, 
compressedStream
);
			}
			
compressedStream
.
(
0
);
			
  = (
)
.
();
			
  = (
)
compressedStream
.
();
			
const
   = 
1024
;
			
  = 
length
 % 
block
;
			
  = 
length
 / 
block
 + (
remain
 ? 
1
 : 
0
);
#define PREFIX writer.WriteString(prefix);
			PREFIX writer.WriteLine(L"class " + className);
			PREFIX writer.WriteLine(L"{");
			PREFIX writer.WriteLine(L"public:");
			PREFIX writer.WriteLine(L"\tstatic const vint parserBufferLength = " + itow(length) + L"; // " + itow(lengthBeforeCompressing) + L" bytes before compressing");
			.
(
); 
.
(
L"\tstatic const vint parserBufferLength = "
 + 
(
length
) + 
L"; // "
 + 
(
lengthBeforeCompressing
) + 
L" bytes before compressing"
);
 			PREFIX writer.WriteLine(L"\tstatic const vint parserBufferBlock = " + itow(block) + L";");
			.
(
); 
.
(
L"\tstatic const vint parserBufferBlock = "
 + 
(
block
) + 
L";"
);
 			PREFIX writer.WriteLine(L"\tstatic const vint parserBufferRemain = " + itow(remain) + L";");
			.
(
); 
.
(
L"\tstatic const vint parserBufferRemain = "
 + 
(
remain
) + 
L";"
);
 			PREFIX writer.WriteLine(L"\tstatic const vint parserBufferRows = " + itow(rows) + L";");
			.
(
); 
.
(
L"\tstatic const vint parserBufferRows = "
 + 
(
rows
) + 
L";"
);
 			PREFIX writer.WriteLine(L"\tstatic const char* parserBuffer[" + itow(rows) + L"];");
			.
(
); 
.
(
L"\tstatic const char* parserBuffer["
 + 
(
rows
) + 
L"];"
);
 .
(
L""
);
			PREFIX writer.WriteLine(L"\tstatic void ReadToStream(vl::stream::MemoryStream& stream)");
			.
(
); 
.
(
L"\tstatic void ReadToStream(vl::stream::MemoryStream& stream)"
);
 			PREFIX writer.WriteLine(L"\t{");
			PREFIX writer.WriteLine(L"\t\tDecompressStream(parserBuffer, " + WString(compress ? L"true" : L"false") + L", parserBufferRows, parserBufferBlock, parserBufferRemain, stream);");
			.
(
); 
.
(
L"\t\tDecompressStream(parserBuffer, "
 + 
(
 ? 
L"true"
 : 
L"false"
) + 
L", parserBufferRows, parserBufferBlock, parserBufferRemain, stream);"
);
 			PREFIX writer.WriteLine(L"\t}");
			PREFIX writer.WriteLine(L"};");
.
(
L""
);
			PREFIX writer.WriteLine(L"const char* " + className + L"::parserBuffer[] = {");
			.
(
); 
.
(
L"const char* "
 + 
 + 
L"::parserBuffer[] = {"
);
 char
 [
block
];
			
const
 wchar_t
* 
 = 
L"0123456789ABCDEF"
;
			
for
 (
  = 
0
; 
i
 < 
rows
; 
i
++)
			{
				
  = 
i
 == 
rows
 - 
1
 ? 
remain
 : 
block
;
				
compressedStream
.
(
buffer
, 
size
);
				PREFIX writer.WriteString(L"\t\"");
for
 (
  = 
0
; 
j
 < 
size
; 
j
++)
				{
					
  = 
buffer
[
j
];
					
.
(
L"\\x"
);
					
.
(
hex
[
byte
 / 
16
]);
					
.
(
hex
[
byte
 % 
16
]);
				}
				
.
(
L"\","
);
			}
			PREFIX writer.WriteLine(L"\t};");
#undef PREFIX
		}
		
bool
 (
<
> 
,
			
<
workflow
::
cppcodegen
::
> 
,
			
<
workflow
::
cppcodegen
::
> 
,
			
bool
 ,
			
const
 filesystem
::
& 
)
		{
			
  = 
([&](
& 
)
			{
				
writer
.
(
L"#include \""
 + 
 + 
L".h\""
);
				
writer
.
(
L""
);
				
writer
.
(
L"namespace vl"
);
				
writer
.
(
L"{"
);
				
writer
.
(
L"\tnamespace presentation"
);
				
writer
.
(
L"\t{"
);
				
writer
.
(
L"\t\tnamespace user_resource"
);
				
writer
.
(
L"\t\t{"
);
				
writer
.
(
L"\t\t\tusing namespace collections;"
);
				
writer
.
(
L"\t\t\tusing namespace stream;"
);
				
writer
.
(
L"\t\t\tusing namespace controls;"
);
				
writer
.
(
L""
);
				{
					
 ;
					{
						
auto
  = 
(
L"Precompiled"
);
						
auto
  = 
precompiled
->GetFolder(
L"Workflow"
);
						
precompiled
->RemoveFolder(
L"Workflow"
);
						
(
resourceStream
);
						
precompiled
->AddFolder(
L"Workflow"
, 
folder
);
					}
					
(
resourceStream
, 
, 
 + 
L"ResourceReader"
, 
L"\t\t\t"
, 
writer
);
					
writer
.
(
L""
);
				}
				{
					
writer
.
(
L"\t\t\tclass "
 + 
 + 
L"ResourceLoaderPlugin : public Object, public IGuiPlugin"
);
					
writer
.
(
L"\t\t\t{"
);
					
writer
.
(
L"\t\t\tpublic:"
);
					
writer
.
(
L""
);
					
writer
.
(
L"\t\t\t\tGUI_PLUGIN_NAME(GacGen_"
 + 
 + 
L"ResourceLoader)"
);
					
writer
.
(
L"\t\t\t\t{"
);
					
writer
.
(
L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Res_Resource);"
);
					
writer
.
(
L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Res_TypeResolvers);"
);
					
writer
.
(
L"#ifdef VCZH_DESCRIPTABLEOBJECT_WITH_METADATA"
);
					
writer
.
(
L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Instance_Reflection);"
);
					
writer
.
(
L"\t\t\t\t\tGUI_PLUGIN_DEPEND(GacUI_Compiler_WorkflowTypeResolvers);"
);
					
writer
.
(
L"#endif"
);
					
writer
.
(
L"\t\t\t\t}"
);
					
writer
.
(
L""
);
					
writer
.
(
L"\t\t\t\tvoid Load()override"
);
					
writer
.
(
L"\t\t\t\t{"
);
					
writer
.
(
L"\t\t\t\t\tList<GuiResourceError> errors;"
);
					
writer
.
(
L"\t\t\t\t\tMemoryStream resourceStream;"
);
					
writer
.
(
L"\t\t\t\t\t"
 + 
 + 
L"ResourceReader::ReadToStream(resourceStream);"
);
					
writer
.
(
L"\t\t\t\t\tresourceStream.SeekFromBegin(0);"
);
					
writer
.
(
L"\t\t\t\t\tGetResourceManager()->LoadResourceOrPending(resourceStream, GuiResourceUsage::InstanceClass);"
);
					
writer
.
(
L"\t\t\t\t}"
);
					
writer
.
(
L""
);
					
writer
.
(
L"\t\t\t\tvoid Unload()override"
);
					
writer
.
(
L"\t\t\t\t{"
);
					
writer
.
(
L"\t\t\t\t}"
);
					
writer
.
(
L"\t\t\t};"
);
					
writer
.
(
L"\t\t\tGUI_REGISTER_PLUGIN("
 + 
 + 
L"ResourceLoaderPlugin)"
);
				}
				
writer
.
(
L"\t\t}"
);
				
writer
.
(
L"\t}"
);
				
writer
.
(
L"}"
);
			});
			
 (
);
			
if
 (
file
.
())
			{
				
 ;
				
::
 ;
				
bool
 ;
				
file
.
ReadAllTextWithEncodingTesting
(
inputText
, 
inputEncoding
, 
inputBom
);
				
if
 (
inputText
 == 
code
)
				{
					
return
 true
;
				}
			}
			
return
 file
.
(
code
, 
true
, 
::
);
		}
	}
}