<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<!-- GRPC CODE GENERATION TARGETS FOR MSBUILD -->
<Project>
  <UsingTask TaskName="GrpcToCSharp" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <!-- The directory where the project is located. This is typically $(ProjectDir) -->
      <OutputDirectory ParameterType="System.String" Required="true" />
      <!-- This is the list of C# target files to be generaterd. This is typically @(Compile) -->
      <SourceFileList ParameterType="System.String" Required="true" />
      <!-- The directory where the .avsc schema files are located. -->
      <GrpcSchemaDirectory ParameterType="System.String" Required="true" />
      <!-- The where gRPC schema generator and dependent libraries are located. -->
      <GrpcBinaryDirectory ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
      <Using Namespace="System" />
      <Using Namespace="System.IO" />
      <Using Namespace="System.Diagnostics" />
      <Using Namespace="System.Threading" />
      <Using Namespace="System.Threading.Tasks" />
      <Code Type="Fragment" Language="cs"><![CDATA[
          // Create a temporary working directory for the log file.
          string tempDir = Path.GetFullPath(Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()));
          Directory.CreateDirectory(tempDir);

          // Get the full path to the directory where the gRPC .proto files are located.
          string grpcSrcFileDirectory = Path.GetFullPath(GrpcSchemaDirectory);
          string grpcToolsDirectory = Path.GetFullPath(GrpcBinaryDirectory);
          string grpcOutputDirectory = Path.GetFullPath(OutputDirectory);
          string grpcPluginName = Path.Combine(GrpcBinaryDirectory, "grpc_csharp_plugin.exe");

          // Get the list of names of .proto files
          string[] sourceFiles = SourceFileList.Split(new char[]{';'});

          string copyright = string.Join(Environment.NewLine,
            "// 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.");


          // Setup the conversion process.
          ProcessStartInfo rProcInfo = new ProcessStartInfo()
          {
              RedirectStandardOutput = true,
              RedirectStandardError = true,
              UseShellExecute = false,
              CreateNoWindow = true,
              FileName = Path.Combine(grpcToolsDirectory ,"protoc.exe")
          };

          bool conversionError = false;
          using (StreamWriter logWriter = new StreamWriter(Path.Combine(tempDir, "GrpcCodeGeneration.log")))
          {
              foreach (string file in sourceFiles)
              {
                  logWriter.WriteLine("Processing file: {0}", file);

                  string fullFileName = Path.Combine(grpcSrcFileDirectory, file);
                  rProcInfo.Arguments = " -I" + grpcSrcFileDirectory + " --csharp_out " + tempDir
                      + " " + fullFileName + " --grpc_out " + tempDir
                      + " --plugin=protoc-gen-grpc=" + grpcPluginName;
                  logWriter.WriteLine("Command: {0}", rProcInfo.Arguments);

                  if (File.Exists(fullFileName))
                  {
                      StringBuilder stdOutBuilder = new StringBuilder();
                      StringBuilder stdErrBuilder = new StringBuilder();

                      // Start the conversion process
                      using (Process rProc = Process.Start(rProcInfo))
                      {
                          // Read the standard out and error on separate threads
                          // simultaneously to avoid deadlock when rProc fills one
                          // of the buffers and waits for this process to read it.
                          // Use fully qualified namespace to avoid conflict
                          // with Task class defined in visual studio.
                          var stdOutTask = System.Threading.Tasks.Task.Run(
                              () => stdOutBuilder.Append(rProc.StandardOutput.ReadToEnd()));
                          var stdErrTask = System.Threading.Tasks.Task.Run(
                              () => stdErrBuilder.Append(rProc.StandardError.ReadToEnd()));

                          rProc.WaitForExit();
                          if (rProc.ExitCode != 0)
                          {
                              conversionError = true;
                          }

                          // Wait for std out and error readers.
                          stdOutTask.Wait();
                          stdErrTask.Wait();
                      }
                      logWriter.WriteLine("[StdOut]:");
                      logWriter.WriteLine(stdOutBuilder.ToString());
                      logWriter.WriteLine("[StdErr]:");
                      logWriter.WriteLine(stdErrBuilder.ToString());
                  }
                  if (!conversionError)
                  {
                      // Get all of the generated C# files and copy to destination with copyright.
                      var genFiles = Directory.EnumerateFiles(tempDir, "*.cs");
                      foreach (string genFile in genFiles)
                      {
                          logWriter.WriteLine("Processing file {0}", genFile);
                          using (StreamReader tmpReader = new StreamReader(genFile))
                          {
                              using (StreamWriter destWriter =
                                  new StreamWriter(Path.Combine(grpcOutputDirectory, Path.GetFileName(genFile))))
                             {
                                 destWriter.WriteLine(copyright);
                                 destWriter.Write(tmpReader.ReadToEnd());
                             }
                          }
                          File.Delete(genFile);
                      }
                  }
              }
          }
          if (!conversionError)
          {
              Directory.Delete(tempDir, recursive : true);
          }
      ]]></Code>
    </Task>
  </UsingTask>
</Project>
