from typing import Optional, Tuple, Union

import flax
import flax.linen as nn
import jax
import jax.numpy as jnp
from flax.core.frozen_dict import FrozenDict

from ..configuration_utils import ConfigMixin, flax_register_to_config
from ..utils import BaseOutput
from .embeddings_flax import FlaxTimestepEmbedding, FlaxTimesteps
from .modeling_flax_utils import FlaxModelMixin
from .unet_ad_blocks_flax import (
    FlaxCrossAttnDownBlockaD,
    FlaxCrossAttnUpBlockaD,
    FlaxDownBlockaD,
    FlaxUNetMidBlockaDCrossAttn,
    FlaxUpBlockaD,
)



@flax.struct.dataclass
class      _A (     _snake_case				):
  SCREAMING_SNAKE_CASE_						:						jnp.ndarray



@flax_register_to_config
class      _A (     nn.Module						,			_snake_case						,			_snake_case				):
  SCREAMING_SNAKE_CASE_						:						int    =32
  SCREAMING_SNAKE_CASE_						:						int    =4
  SCREAMING_SNAKE_CASE_						:						int    =4
  SCREAMING_SNAKE_CASE_						:						Tuple[str]    =(
      "CrossAttnDownBlock2D",
      "CrossAttnDownBlock2D",
      "CrossAttnDownBlock2D",
      "DownBlock2D",
  )
  SCREAMING_SNAKE_CASE_						:						Tuple[str]    =("UpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D", "CrossAttnUpBlock2D")
  SCREAMING_SNAKE_CASE_						:						Union[bool, Tuple[bool]]    =False
  SCREAMING_SNAKE_CASE_						:						Tuple[int]    =(3_20, 6_40, 12_80, 12_80)
  SCREAMING_SNAKE_CASE_						:						int    =2
  SCREAMING_SNAKE_CASE_						:						Union[int, Tuple[int]]    =8
  SCREAMING_SNAKE_CASE_						:						Optional[Union[int, Tuple[int]]]    =None
  SCREAMING_SNAKE_CASE_						:						int    =12_80
  SCREAMING_SNAKE_CASE_						:						float    =0.0
  SCREAMING_SNAKE_CASE_						:						bool    =False
  SCREAMING_SNAKE_CASE_						:						jnp.dtype    =jnp.floataa
  SCREAMING_SNAKE_CASE_						:						bool    =True
  SCREAMING_SNAKE_CASE_						:						int    =0
  SCREAMING_SNAKE_CASE_						:						bool    =False






  def 		_a       (self ,					SCREAMING_SNAKE_CASE_						)		->   int:





       '''simple docstring'''





       UpperCamelCase__					    =   (1, self.in_channels, self.sample_size, self.sample_size)
       UpperCamelCase__					    =   jnp.zeros(__snake_case ,					dtype=jnp.floataa						)
       UpperCamelCase__					    =   jnp.ones((1,) ,					dtype=jnp.intaa						)
       UpperCamelCase__					    =   jnp.zeros((1, 1, self.cross_attention_dim) ,					dtype=jnp.floataa						)

       UpperCamelCase__					    =   jax.random.split(__snake_case						)
       UpperCamelCase__					    =   {"""params""": params_rng, """dropout""": dropout_rng}

       return self.init(__snake_case ,					__snake_case ,					__snake_case ,					__snake_case						)["params"]






  def 		_a       (self						)		->   Union[str, Any]:





       '''simple docstring'''





       UpperCamelCase__					    =   self.block_out_channels
       UpperCamelCase__					    =   block_out_channels[0] * 4

       if self.num_attention_heads is not None:
            raise ValueError(
                '''At the moment it is not possible to define the number of attention heads via `num_attention_heads` because of a naming issue as described in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131. Passing `num_attention_heads` will only be supported in diffusers v0.19.'''						)

       # If `num_attention_heads` is not defined (which is the case for most models)
       # it will default to `attention_head_dim`. This looks weird upon first reading it and it is.
       # The reason for this behavior is to correct for incorrectly named variables that were introduced
       # when this library was created. The incorrect naming was only discovered much later in https://github.com/huggingface/diffusers/issues/2011#issuecomment-1547958131
       # Changing `attention_head_dim` to `num_attention_heads` for 40,000+ configurations is too backwards breaking
       # which is why we correct for the naming here.
       UpperCamelCase__					    =   self.num_attention_heads or self.attention_head_dim

       # input
       UpperCamelCase__					    =   nn.Conv(
           block_out_channels[0] ,					kernel_size=(3, 3) ,					strides=(1, 1) ,					padding=((1, 1), (1, 1)) ,					dtype=self.dtype ,					)

       # time
       UpperCamelCase__					    =   FlaxTimesteps(
           block_out_channels[0] ,					flip_sin_to_cos=self.flip_sin_to_cos ,					freq_shift=self.config.freq_shift						)
       UpperCamelCase__					    =   FlaxTimestepEmbedding(__snake_case ,					dtype=self.dtype						)

       UpperCamelCase__					    =   self.only_cross_attention
       if isinstance(__snake_case ,					__snake_case						):
            UpperCamelCase__					    =   (only_cross_attention,) * len(self.down_block_types						)

       if isinstance(__snake_case ,					__snake_case						):
            UpperCamelCase__					    =   (num_attention_heads,) * len(self.down_block_types						)

       # down
       UpperCamelCase__					    =   []
       UpperCamelCase__					    =   block_out_channels[0]
       for i, down_block_type in enumerate(self.down_block_types						):
            UpperCamelCase__					    =   output_channel
            UpperCamelCase__					    =   block_out_channels[i]
            UpperCamelCase__					    =   i == len(__snake_case						) - 1

            if down_block_type == "CrossAttnDownBlock2D":
                 UpperCamelCase__					    =   FlaxCrossAttnDownBlockaD(
                     in_channels=__snake_case ,					out_channels=__snake_case ,					dropout=self.dropout ,					num_layers=self.layers_per_block ,					num_attention_heads=num_attention_heads[i] ,					add_downsample=not is_final_block ,					use_linear_projection=self.use_linear_projection ,					only_cross_attention=only_cross_attention[i] ,					use_memory_efficient_attention=self.use_memory_efficient_attention ,					dtype=self.dtype ,					)
            else:
                 UpperCamelCase__					    =   FlaxDownBlockaD(
                     in_channels=__snake_case ,					out_channels=__snake_case ,					dropout=self.dropout ,					num_layers=self.layers_per_block ,					add_downsample=not is_final_block ,					dtype=self.dtype ,					)

            down_blocks.append(__snake_case						)
       UpperCamelCase__					    =   down_blocks

       # mid
       UpperCamelCase__					    =   FlaxUNetMidBlockaDCrossAttn(
           in_channels=block_out_channels[-1] ,					dropout=self.dropout ,					num_attention_heads=num_attention_heads[-1] ,					use_linear_projection=self.use_linear_projection ,					use_memory_efficient_attention=self.use_memory_efficient_attention ,					dtype=self.dtype ,					)

       # up
       UpperCamelCase__					    =   []
       UpperCamelCase__					    =   list(reversed(__snake_case						)						)
       UpperCamelCase__					    =   list(reversed(__snake_case						)						)
       UpperCamelCase__					    =   list(reversed(__snake_case						)						)
       UpperCamelCase__					    =   reversed_block_out_channels[0]
       for i, up_block_type in enumerate(self.up_block_types						):
            UpperCamelCase__					    =   output_channel
            UpperCamelCase__					    =   reversed_block_out_channels[i]
            UpperCamelCase__					    =   reversed_block_out_channels[min(i + 1 ,					len(__snake_case						) - 1						)]

            UpperCamelCase__					    =   i == len(__snake_case						) - 1

            if up_block_type == "CrossAttnUpBlock2D":
                 UpperCamelCase__					    =   FlaxCrossAttnUpBlockaD(
                     in_channels=__snake_case ,					out_channels=__snake_case ,					prev_output_channel=__snake_case ,					num_layers=self.layers_per_block + 1 ,					num_attention_heads=reversed_num_attention_heads[i] ,					add_upsample=not is_final_block ,					dropout=self.dropout ,					use_linear_projection=self.use_linear_projection ,					only_cross_attention=only_cross_attention[i] ,					use_memory_efficient_attention=self.use_memory_efficient_attention ,					dtype=self.dtype ,					)
            else:
                 UpperCamelCase__					    =   FlaxUpBlockaD(
                     in_channels=__snake_case ,					out_channels=__snake_case ,					prev_output_channel=__snake_case ,					num_layers=self.layers_per_block + 1 ,					add_upsample=not is_final_block ,					dropout=self.dropout ,					dtype=self.dtype ,					)

            up_blocks.append(__snake_case						)
            UpperCamelCase__					    =   output_channel
       UpperCamelCase__					    =   up_blocks

       # out
       UpperCamelCase__					    =   nn.GroupNorm(num_groups=32 ,					epsilon=1E-5						)
       UpperCamelCase__					    =   nn.Conv(
           self.out_channels ,					kernel_size=(3, 3) ,					strides=(1, 1) ,					padding=((1, 1), (1, 1)) ,					dtype=self.dtype ,					)






  def __call__(self ,					SCREAMING_SNAKE_CASE_ ,					SCREAMING_SNAKE_CASE_ ,					SCREAMING_SNAKE_CASE_ ,					SCREAMING_SNAKE_CASE_=None ,					SCREAMING_SNAKE_CASE_=None ,					SCREAMING_SNAKE_CASE_ = True ,					SCREAMING_SNAKE_CASE_ = False ,					)		->   Union[str, Any]:





       '''simple docstring'''





       if not isinstance(__snake_case ,					jnp.ndarray						):
            UpperCamelCase__					    =   jnp.array([timesteps] ,					dtype=jnp.intaa						)
       elif isinstance(__snake_case ,					jnp.ndarray						) and len(timesteps.shape						) == 0:
            UpperCamelCase__					    =   timesteps.astype(dtype=jnp.floataa						)
            UpperCamelCase__					    =   jnp.expand_dims(__snake_case ,					0						)

       UpperCamelCase__					    =   self.time_proj(__snake_case						)
       UpperCamelCase__					    =   self.time_embedding(__snake_case						)

       # 2. pre-process
       UpperCamelCase__					    =   jnp.transpose(__snake_case ,					(0, 2, 3, 1)						)
       UpperCamelCase__					    =   self.conv_in(__snake_case						)

       # 3. down
       UpperCamelCase__					    =   (sample,)
       for down_block in self.down_blocks:
            if isinstance(__snake_case ,					__snake_case						):
                 UpperCamelCase__					    =   down_block(__snake_case ,					__snake_case ,					__snake_case ,					deterministic=not train						)
            else:
                 UpperCamelCase__					    =   down_block(__snake_case ,					__snake_case ,					deterministic=not train						)
            down_block_res_samples += res_samples

       if down_block_additional_residuals is not None:
            UpperCamelCase__					    =   ()

            for down_block_res_sample, down_block_additional_residual in zip(
                __snake_case ,					__snake_case						):
                 down_block_res_sample += down_block_additional_residual
                 new_down_block_res_samples += (down_block_res_sample,)

            UpperCamelCase__					    =   new_down_block_res_samples

       # 4. mid
       UpperCamelCase__					    =   self.mid_block(__snake_case ,					__snake_case ,					__snake_case ,					deterministic=not train						)

       if mid_block_additional_residual is not None:
            sample += mid_block_additional_residual

       # 5. up
       for up_block in self.up_blocks:
            UpperCamelCase__					    =   down_block_res_samples[-(self.layers_per_block + 1) :]
            UpperCamelCase__					    =   down_block_res_samples[: -(self.layers_per_block + 1)]
            if isinstance(__snake_case ,					__snake_case						):
                 UpperCamelCase__					    =   up_block(
                     __snake_case ,					temb=__snake_case ,					encoder_hidden_states=__snake_case ,					res_hidden_states_tuple=__snake_case ,					deterministic=not train ,					)
            else:
                 UpperCamelCase__					    =   up_block(__snake_case ,					temb=__snake_case ,					res_hidden_states_tuple=__snake_case ,					deterministic=not train						)

        # 6. post-process
       UpperCamelCase__					    =   self.conv_norm_out(__snake_case						)
       UpperCamelCase__					    =   nn.silu(__snake_case						)
       UpperCamelCase__					    =   self.conv_out(__snake_case						)
       UpperCamelCase__					    =   jnp.transpose(__snake_case ,					(0, 3, 1, 2)						)

       if not return_dict:
            return (sample,)

       return FlaxUNetaDConditionOutput(sample=__snake_case						)







'''simple docstring'''


def      snake_case_  (    SCREAMING_SNAKE_CASE__	):







				"""simple docstring"""





				return "".join(chr(ord(SCREAMING_SNAKE_CASE__	) - 32	) if """a""" <= char <= """z""" else char for char in word	)


if __name__ == "__main__":
				from doctest import testmod

				testmod()




