_F='layers'
_E='zip_dir'
_D='S3Bucket'
_C='functions'
_B='_is_restoring_state'
_A=None
import base64,hashlib,logging,os,os.path
from typing import Dict,List,Optional,Tuple
from localstack import config
from localstack import config as localstack_config
from localstack.services.awslambda import lambda_api
from localstack.services.awslambda.event_source_listeners.event_source_listener import EventSourceListener
from localstack.services.awslambda.lambda_api import LAMBDA_ZIP_FILE_NAME
from localstack.services.awslambda.lambda_models import awslambda_stores
from localstack.services.awslambda.lambda_utils import get_zip_bytes
from localstack.utils.aws.aws_models import LambdaFunction
from localstack.utils.files import cp_r,file_exists_not_empty,load_file,mkdir,save_file
from localstack.utils.patch import patch
from localstack.utils.strings import short_uid
from localstack_ext.bootstrap.aws_models import LambdaLayer
LOG=logging.getLogger(__name__)
LAMBDA_ASSETS_ROOT='lambda'
def restore_backend_state():
	A=[]
	for (J,D) in awslambda_stores.items():
		for (K,B) in D.items():
			A.append(B)
			for E in B.event_source_mappings:EventSourceListener.start_listeners(E)
	C=[B for A in A for B in A.lambdas.values()];F=[A for A in C if not isinstance(A,LambdaLayer)];G=[A for A in C if isinstance(A,LambdaLayer)]
	for H in G:do_restore_backend_state(H)
	for I in F:do_restore_backend_state(I)
def do_restore_backend_state(function_or_layer):
	A=function_or_layer
	try:
		A._is_restoring_state=True
		if isinstance(A,LambdaLayer):
			for B in A.versions.values():store_and_get_layer_code_archive(lambda_layer=A,layer_version=B,code={},zip_file_content=_A)
		else:A.state='Pending';lambda_api.set_function_code(A)
	except Exception as C:LOG.info('Unable to load user code for Lambda function %s: %s',A.arn(),C)
	finally:delattr(A,_B)
def _get_details_for_lambda_layer_versions(lambda_layer):return[(B,C,A.get('LayerVersionArn'))for(B,A)in lambda_layer.versions.items()if(C:=A.get(_E))]
def _asset_path_layer(arn):A=arn.split(':');B=A[-1];C=f"{A[-2]}_{B}";D=A[3];return os.path.join(_F,D,C)
def _asset_path_function(arn):A=arn.split(':');B=A[-1];C=A[3];return os.path.join(_C,C,B)
def store_and_get_layer_code_archive(lambda_layer,layer_version,code,zip_file_content=_A):
	E=zip_file_content;D=layer_version;B=lambda_layer;A=f"{get_persistent_zip_file_path(B,_F)}_{D['Version']}";G=code.get(_D)==localstack_config.BUCKET_MARKER_LOCAL;H=getattr(B,_B,False)
	if H and A and file_exists_not_empty(A):E=load_file(A,mode='rb')
	C=store_layer_archive(code,layer=B,layer_version=D,zip_file_content=E)
	if C and A and not G:
		F=os.path.join(C,LAMBDA_ZIP_FILE_NAME)
		if F:cp_r(F,A)
	return C
def store_layer_archive(code,layer,layer_version,zip_file_content=_A):
	F='S3Key';D=layer_version;B=code;A=zip_file_content;E=B.get(_D)==config.BUCKET_MARKER_LOCAL
	if E and config.LAMBDA_REMOTE_DOCKER:G='Please note that Lambda Layer mounts (bucket name "%s") cannot be used with LAMBDA_REMOTE_DOCKER=1';raise Exception(G%config.BUCKET_MARKER_LOCAL)
	if E:layer.cwd=B.get(F);return B[F]
	A=A or get_zip_bytes(B)
	if not A:return
	C=os.path.join(config.dirs.tmp,f"layer.zipfile.{short_uid()}");mkdir(C);H=os.path.join(C,LAMBDA_ZIP_FILE_NAME);I=base64.standard_b64encode(hashlib.sha256(A).digest());save_file(H,A);D[_E]=C;D['CodeSize']=len(A);D['CodeSha256']=I.decode('utf-8');return C
def get_persistent_zip_file_path(lambda_function,subdir=_C):A=lambda_function;C=A.region();B=os.path.join(config.dirs.data,LAMBDA_ASSETS_ROOT,subdir,C);mkdir(B);D=os.path.join(B,A.name());return D
@patch(lambda_api.store_and_get_lambda_code_archive)
def store_and_get_lambda_code_archive(fn,lambda_function,zip_file_content=_A):
	E=zip_file_content;B=lambda_function;A=get_persistent_zip_file_path(B,_C);F=B.code.get(_D)==localstack_config.BUCKET_MARKER_LOCAL;G=getattr(B,_B,False)
	if G and A and file_exists_not_empty(A):E=load_file(A,mode='rb')
	C=fn(B,E)
	if C and A and not F:
		D=C[1]
		if D and os.path.exists(D):cp_r(D,A)
	return C