BeginPackage["FusionAtlas`PackageData`",{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`FindAllBigraphs`","FusionAtlas`KnapsackTest`","FusionAtlas`TensorSolver`","FusionAtlas`FindGraphPartners`","FusionAtlas`GraphPlanarAlgebra`","FusionAtlas`GraphPairs`","FusionAtlas`PairOdometer`"}];

ValuesAsString;PackageData;MatchingValues;DefiniteValues;

{PackageEverything,PackageCachedRootReduce,PackageDimensions,PackageBigraphExtensions,PackageBifusionAlgebras,PackageLowWeightSpaces,PackageAlgebraicIntegerTest,PackageKnapsackTest,PackageFindGraphPartners,PackageObstructions,PackageLowestWeightEigenspaces,PackageIdempotents,PackagePairExtensions};

Begin["`Private`"];

DefiniteValues[s_Symbol]:=Cases[DownValues[s]~Join~SubValues[s],rule:(pattern_/;FreeQ[pattern,Blank]:>_):>rule]

MatchingValues[s_Symbol,p_]:=Cases[DownValues[s]~Join~SubValues[s],rule:(pattern_/;MatchQ[pattern/.HoldPattern->Hold,Hold[p]]:>_):>rule]

MatchingValues[s_Symbol,p_,vp_]:=Cases[DownValues[s]~Join~SubValues[s],rule:(pattern_/;MatchQ[pattern/.HoldPattern->Hold,Hold[p]]:>value_/;MatchQ[value,vp]):>rule]

ConvertRuleToAssignmentString[a_HoldPattern:>b_]:=StringTake[ToString[a,InputForm,CharacterEncoding->"PrintableASCII"],{13,-2}]<>":="<>ToString[b,InputForm,CharacterEncoding->"PrintableASCII"]<>"\n"

ValuesAsString[s_Symbol,p_]:=StringJoin@@(ConvertRuleToAssignmentString/@MatchingValues[s,p])

WriteRule[filename_,a_HoldPattern:>b_]:=
(WriteString[filename,StringTake[ToString[a,InputForm,CharacterEncoding->"PrintableASCII"],{13,-2}]<>":="];
CautiousWriteString[filename,b,InputForm,CharacterEncoding->"PrintableASCII"];
WriteString[filename,"\n"];)

CautiousWriteString[filename_,s_Symbol,options___]:=WriteString[filename,ToString[s,options]]
CautiousWriteString[filename_,s_String,options___]:=WriteString[filename,"\""<>s<>"\""]
CautiousWriteString[filename_,s_Integer,options___]:=WriteString[filename,ToString[s,options]]
CautiousWriteString[filename_,s_Real,options___]:=WriteString[filename,ToString[s,options]]
CautiousWriteString[filename_,x_Plus,options___]:=WriteString[filename,ToString[x,options]]
CautiousWriteString[filename_,x_Times,options___]:=WriteString[filename,ToString[x,options]]
CautiousWriteString[filename_,x_TensorProduct,options___]:=WriteString[filename,ToString[x,options]]
CautiousWriteString[filename_,x_CircleTimes,options___]:=WriteString[filename,ToString[x,options]]
CautiousWriteString[filename_,{},options___]:=WriteString[filename,"{}"]
CautiousWriteString[filename_,{x__},options___]:=
(WriteString[filename,"{"];
(CautiousWriteString[filename,#,options];WriteString[filename,", "])&/@Most[{x}];
CautiousWriteString[filename,Last[{x}],options];
WriteString[filename,"}"];)
CautiousWriteString[filename_,f_[x___],options___]:=
(WriteString[filename,ToString[f,options]];WriteString[filename,"["];
(CautiousWriteString[filename,#,options];WriteString[filename,", "])&/@Most[{x}];
CautiousWriteString[filename,Last[{x}],options];
WriteString[filename,"]"];)

SafeCreateDirectory[dir_String]:=If[Length[FileNames[dir]]==0,CreateDirectory[dir]]

Options[PackageData]={"Needs"->{},"ExtraPackageCode"->"","ExtraPrivateCode"->"","LoadPreexistingPackage"->True,"Message"->"FusionAtlas::loading","UseGzip"->False,"ByteCountLimit"->∞};
PackageData[s_Symbol,p_,packagePath:{__String},opts___]:=PackageData[{{s,p}},FusionAtlasDataDirectory[],packagePath,opts]
PackageData[s_Symbol,p_,baseDirectory_String,packagePath:{__String},opts___]:=PackageData[{{s,p}},baseDirectory,packagePath,opts]
PackageData[patterns:{{_Symbol,___}..},packagePath:{__String},opts___]:=PackageData[patterns,FusionAtlasDataDirectory[],packagePath,opts]
PackageData[patterns:{{_Symbol,___}..},baseDirectory_String,packagePath:{__String},opts___]:=AbortProtect[Module[{fullPackagePath,package,directory,filename,contentsTop, contentsBottom,needs,extraPackageCode,extraPrivateCode,loadPreexistingPackage,message,useGzip,byteCountLimit},
needs="Needs"/.{opts}/.Options[PackageData];
extraPackageCode="ExtraPackageCode"/.{opts}/.Options[PackageData];
extraPrivateCode="ExtraPrivateCode"/.{opts}/.Options[PackageData];
loadPreexistingPackage="LoadPreexistingPackage"/.{opts}/.Options[PackageData];
message="Message"/.{opts}/.Options[PackageData];
useGzip="UseGzip"/.{opts}/.Options[PackageData];
byteCountLimit="ByteCountLimit"/.{opts}/.Options[PackageData];
SafeCreateDirectory[baseDirectory];
SetDirectory[baseDirectory];
fullPackagePath={"FusionAtlas","Data"}~Join~packagePath;
directory=ToFileName[Most[fullPackagePath]];
If[Length[FileNames[fullPackagePath[[-2]],ToFileName[Drop[fullPackagePath,-2]]]]==0,SafeCreateDirectory[directory]];
package=StringJoin@@(Flatten[Transpose[{fullPackagePath,Table["`",{Length[fullPackagePath]}]}],1]);
filename=ToFileName[Most[fullPackagePath],Last[fullPackagePath]<>".m"];
If[loadPreexistingPackage∧!MemberQ[$ContextPath,package],
If[useGzip∧Length[FileNames[filename]]==0∧Length[FileNames[filename<>".gz"]]≠0,
SetDirectory[directory];
Run["gzip -d "<>Last[fullPackagePath]<>".m.gz"];
ResetDirectory[]
];
If[Length[FileNames[filename]]≠0,Get[package]]
];
contentsTop="BeginPackage[\""<>package<>"\""<>If[MatchQ[needs,{__String}],", "<>ToString[needs,InputForm],""]<>"]"<>"\n"
<>"Message["<>message<>",\""<>package<>"\"]"<>"\n"
<>extraPackageCode<>"\n"
<>"Begin[\"`Private`\"]"<>"\n"
<>extraPrivateCode<>"\n";
contentsBottom="End[]\n"<>"EndPackage[]";
If[Length[FileNames[filename]]≠0,DeleteFile[filename]];
If[useGzip∧Length[FileNames[filename<>".gz"]]≠0,DeleteFile[filename<>".gz"]];
WriteString[filename,contentsTop];
(Function[{rule},WriteRule[filename,rule]]/@Cases[MatchingValues@@#,((p_:>v_)/;ByteCount[v]≤byteCountLimit)])&/@patterns;
WriteString[filename,contentsBottom];
Close[filename];
If[useGzip,SetDirectory[directory];Run["gzip --rsync "<>Last[fullPackagePath]<>".m"];ResetDirectory[]];
ResetDirectory[];]]

PackageEverything[index_]:=Module[{},
PackageCachedRootReduce[];
(*PackageDimensions[];*)
PackageAlgebraicIntegerTest[];
PackageFindGraphPartners[];
PackageObstructions[];
PackageBifusionAlgebras[];
PackageBigraphExtensions[index];
]

PackageCachedRootReduce[]:=PackageData[
cachedRootReduce,HoldPattern[cachedRootReduce[n_/;FreeQ[n,Blank]]],
{"RootReduce"},
"Needs"->{"FusionAtlas`"}
]

PackageDimensions[]:=PackageData[
{{DimensionsByDepth,HoldPattern[DimensionsByDepth[_GradedBigraph|_GradedGraph]]},
{ReducedDimensionsByDepth,HoldPattern[ReducedDimensionsByDepth[_GradedBigraph|_GradedGraph]]},
{DimensionOfGenerator,HoldPattern[DimensionOfGenerator[_GradedBigraph|_GradedGraph]]},
{ReducedDimensionOfGenerator,HoldPattern[ReducedDimensionOfGenerator[_GradedBigraph|_GradedGraph]]}},
{"Dimensions"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`"}
]

PackageLowWeightSpaces[]:=PackageData[
DimensionOfLowWeightSpace,DimensionOfLowWeightSpace[_GradedBigraph][_Integer],
{"DimensionOfLowWeightSpace"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`"}
]

PackageAlgebraicIntegerTest[]:=PackageData[
AlgebraicIntegerTest,AlgebraicIntegerTest[_GradedBigraph],
{"AlgebraicIntegerTest"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`FindAllBigraphs`"}
]

PackageKnapsackTest[]:=PackageData[
KnapsackTest,KnapsackTest[_GradedBigraph],
{"KnapsackTest"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`KnapsackTest`"}
]

PackageObstructions[]:=PackageData[
{{KnownObstructions,KnownObstructions[_GradedBigraph],{}},{FindAllObstructions,FindAllObstructions[_GradedBigraph]}},
{"Obstructions"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`FindAllBigraphs`"}
]

PackageFindGraphPartners[]:=PackageData[
{{FindGraphPartners,HoldPattern[FindGraphPartners[_GradedBigraph]]},{FindGraphPartnersTimeConstraint,HoldPattern[FindGraphPartnersTimeConstraint[_GradedBigraph]]}},
{"FindGraphPartners"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`FindGraphPartners`"}
]

PackageBigraphExtensions[norm_]:=PackageData[
{(*{FindBigraphExtensions,HoldPattern[FindBigraphExtensions[norm0_/;norm0≤norm+0.0001][_,_]]},{FindBigraphExtensionsUpToRank,HoldPattern[FindBigraphExtensionsUpToRank[norm0_/;norm0≤norm+0.0001][_,_]]},*){FindAllBigraphs,HoldPattern[FindAllBigraphs[{_,norm0_/;norm0≤norm+0.0001},_Integer,_GradedBigraph]]}},
{"BigraphExtensions","index"<>StringReplace[ToString[N[norm]],"."->"p"]},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`FindAllBigraphs`"}
]

PackageBifusionAlgebras[]:=PackageData[
{{FindBifusionAlgebras,HoldPattern[FindBifusionAlgebras[_GradedBigraph,_GradedBigraph]]},{FusionAtlas`TensorSolver`Private`FindBifusionAlgebrasTimeConstraint,HoldPattern[FusionAtlas`TensorSolver`Private`FindBifusionAlgebrasTimeConstraint[_GradedBigraph,_GradedBigraph]]},{FindFusionAlgebras,HoldPattern[FindFusionAlgebras[_GradedGraph]]},{FusionAtlas`TensorSolver`Private`FindFusionAlgebrasTimeConstraint,HoldPattern[FusionAtlas`TensorSolver`Private`FindFusionAlgebrasTimeConstraint[_GradedGraph]]}},
{"BifusionAlgebras"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`TensorSolver`"}
]

PackageLowestWeightEigenspaces[g_GradedBigraph]:=PackageData[
LowestWeightEigenspace,HoldPattern[LowestWeightEigenspace[g,_]],
{GraphToString[g],"LowestWeightEigenspace"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`GraphPlanarAlgebra`"}
]

PackageIdempotents[g_GradedBigraph]:=PackageData[
{{JonesWenzlIdempotent,HoldPattern[JonesWenzlIdempotent[g,_,_]]}},
{GraphToString[g],"Idempotents"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`GraphPlanarAlgebra`"}
]

PackagePairExtensions[g_GradedBigraph]:=PackageData[
{{FindBigraphPairExtensionsUpToDepth,HoldPattern[FindBigraphPairExtensionsUpToDepth[_][BigraphWithDuals[g,_],BigraphWithDuals[_,_],__]]}},
{GraphToString[g],"PairExtensions"},
"Needs"->{"FusionAtlas`","FusionAtlas`Bigraphs`","FusionAtlas`GraphPairs`","FusionAtlas`PairOdometer`"}
]

End[];

EndPackage[];