1 module armos.command.generator.project;
2 
3 auto generateProject(string[] args, ){
4     ProjectConfig config = parseProject(args);
5     import std.process;
6     import std.conv;
7     import std..string;
8     auto pipes = pipeProcess(["dub","init", "-n", "--format="~config.format.to!string, config.path], Redirect.stdin | Redirect.stdout);
9     pipes.stdin.close;
10     pipes.stdout.close;
11     wait(pipes.pid);
12 
13     addArmosDependency(config);
14     setupMainAppSource(config);
15     setupGlslify(config);
16 }
17 
18 import armos.command.generator.component;
19 
20 private struct ProjectConfig {
21     string path;
22     string name;
23     PackageRecipeFormat format = PackageRecipeFormat.json;
24     Component[] components;
25     //camera
26     //fbo
27     //material
28     //bufferentity
29 }
30 
31 private enum PackageRecipeFormat{
32     json, 
33     sdl 
34 }
35 
36 private ProjectConfig  parseProject(string[] args){
37     import std.functional;
38     string path = (args.length>0 && args[0][0] != '-')?args[0]:"./";
39     import std.path;
40     if(!path.isAbsolute){
41         import std.file;
42         path = buildPath(getcwd, path);
43     }
44     string name = path.baseName;
45 
46     Component[] components;
47     DefaultCamera.add(components, args);
48 
49     ProjectConfig config = {
50         path: path, 
51         name: name, 
52         components: components, 
53 
54     };
55     return config;
56 }
57 
58 private auto addArmosDependency(in ProjectConfig config){
59     switch (config.format) {
60         case PackageRecipeFormat.sdl:
61             addArmosDependencyToSDL(config);
62             break;
63         case PackageRecipeFormat.json:
64             addArmosDependencyToJSON(config);
65             break;
66         default:
67             assert(0);
68     }
69 }
70 
71 private auto addArmosDependencyToSDL(in ProjectConfig config){
72     import std.file;
73     import std.path;
74     string text = readText(buildPath(config.path, "dub.sdl"));
75     import std.stdio;
76     text.writeln;
77     assert(0, "TODO");
78 }
79 
80 private auto addArmosDependencyToJSON(in ProjectConfig config){
81     import std.file;
82     import std.path;
83     immutable dubFilePath = buildPath(config.path, "dub.json");
84     string text = readText(dubFilePath);
85     import std.json;
86     JSONValue json = parseJSON(text);
87     JSONValue armosPackage = JSONValue("armos");
88     json.object["dependencies"] = JSONValue();
89     json.object["dependencies"]["armos"] = JSONValue(latestPackageVersion("armos"));
90     write(dubFilePath, toJSON(json, true));
91 }
92 
93 private string latestPackageVersion(in string name){
94     import std.process;
95     import std.algorithm;
96     import std.array;
97     import std..string;
98     import std.typecons;
99     auto packages = executeShell("dub list").output.strip.split("\n").map!((p){auto splitted = p.strip.split(" ");return tuple!("name", "ver", "path")(splitted[0], splitted[1][0..$-1], splitted[2]);});
100     return packages.filter!(p => p.name == name).array[$-1].ver;
101 }
102 
103 private void setupMainAppSource(in ProjectConfig config){
104     string[] defines;
105     string[] setups;
106     string[] updates;
107     string[] draws;
108     foreach (component; config.components) {
109         defines ~= component.define;
110         setups  ~= component.setup;
111         updates ~= component.update;
112         draws   ~= component.draw;
113     }
114 
115     import armos.command.generator.mainapp;
116     immutable sourceText = mainAppSourceTemplate(defines, setups, updates, draws);
117     import std.file;
118     import std.path;
119     immutable appSourcePath = buildPath(config.path, "source", "app.d");
120     write(appSourcePath, sourceText);
121 }
122 
123 private void setupGlslify(in ProjectConfig config){
124     import std.process;
125     if(execute(["which", "glslify"]).status != 0){
126         execute(["npm", "install", "-g", "glslify"], null, Config.none, size_t.max, config.path); 
127     }
128     execute(["npm", "init", "-y"], null, Config.none, size_t.max, config.path); 
129 }
130