/*
 * Copyright (C) 2009-2019 Lightbend Inc. <https://www.lightbend.com>
 */

package play.mvc;

import akka.stream.javadsl.Source;
import akka.util.ByteString;
import play.api.mvc.MultipartFormData;
import play.core.formatters.Multipart;
import scala.Option;

import java.nio.charset.Charset;
import java.util.concurrent.ThreadLocalRandom;

public class MultipartFormatter {

  public static String randomBoundary() {
    return Multipart.randomBoundary(18, ThreadLocalRandom.current());
  }

  public static String boundaryToContentType(String boundary) {
    return "multipart/form-data; boundary=" + boundary;
  }

  public static Source<ByteString, ?> transform(
      Source<? super Http.MultipartFormData.Part<Source<ByteString, ?>>, ?> parts,
      String boundary) {
    Source<MultipartFormData.Part<akka.stream.scaladsl.Source<ByteString, ?>>, ?> source =
        parts.map(
            (part) -> {
              if (part instanceof Http.MultipartFormData.DataPart) {
                Http.MultipartFormData.DataPart dp = (Http.MultipartFormData.DataPart) part;
                return (MultipartFormData.Part)
                    new MultipartFormData.DataPart(dp.getKey(), dp.getValue());
              } else if (part instanceof Http.MultipartFormData.FilePart) {
                Http.MultipartFormData.FilePart fp = (Http.MultipartFormData.FilePart) part;
                if (fp.ref instanceof Source) {
                  Source ref = (Source) fp.ref;
                  Option<String> ct = Option.apply(fp.getContentType());
                  return (MultipartFormData.Part)
                      new MultipartFormData.FilePart<akka.stream.scaladsl.Source<ByteString, ?>>(
                          fp.getKey(),
                          fp.getFilename(),
                          ct,
                          ref.asScala(),
                          fp.getFileSize(),
                          fp.getDispositionType());
                }
              }
              throw new UnsupportedOperationException("Unsupported Part Class");
            });

    return source.via(Multipart.format(boundary, Charset.defaultCharset(), 4096));
  }
}

@@ -765,24 +765,59 @@
 boundary) %7B%0A
+    @SuppressWarnings(%22unchecked%22)%0A
     Source%3CM
@@ -930,14 +930,12 @@
     
-(
 part
-)
  -%3E 
@@ -1349,16 +1349,19 @@
 FilePart
+%3C?%3E
  fp = (H
@@ -1386,24 +1386,27 @@
 ata.FilePart
+%3C?%3E
 ) part;%0A    
@@ -1477,22 +1477,52 @@
 urce
- ref = (Source
+%3CByteString, ?%3E ref = (Source%3CByteString, ?%3E
 ) fp
@@ -1629,55 +1629,8 @@
 urn 
-(MultipartFormData.Part)%0A                      
 new 
@@ -1719,28 +1719,24 @@
             
-    
 fp.getKey(),
@@ -1732,28 +1732,24 @@
 p.getKey(),%0A
-    
             
@@ -1802,20 +1802,12 @@
     
-   
- 
 ct,%0A
-    
     
@@ -1853,36 +1853,32 @@
                 
-    
 fp.getFileSize()
@@ -1875,28 +1875,24 @@
 FileSize(),%0A
-    
             

Suppress unchecked cast warnings in MultipartFormatter