<commit_before><link rel="import" href="../bower_components/polymer/polymer.html">
<script type="application/javascript" src="../lib/task.js"></script>
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>

<polymer-element name="gdrive-data" attributes="loggedIn profileName profileImage modelReady">
  <template>

  </template>
	<script>
		(function() {
				var nextInstanceId_ = 0;
				var instanceKeys_ = [];
				var instanceMap_ = new WeakMap();
				var addInstance_ = function (instance) {
						for (var i = 0; i < instanceKeys_.length; i++) {
								if (!instanceMap_.has(instanceKeys_[i])) {
										instanceMap_.set(instanceKeys_[i], instance);
										return;
								}
						}
						var key = {id: nextInstanceId_++};
						instanceKeys_.push(key);
						instanceMap_.set(key, instance);;
				}
				var notifyInstances_ = function (event, msg) {
						for (var i = 0; i < instanceKeys_.length; i++) {
								var key = instanceKeys_[i];
								if (instanceMap_.has(key)) {
										instanceMap_.get(key).fire(event, msg);
								}
						}
				}
				var updateModelReady_ = function () {
						for (var i = 0; i < instanceKeys_.length; i++) {
								var key = instanceKeys_[i];
								if (instanceMap_.has(key)) {
										instanceMap_.get(key).modelReady = initialized_;
								}
						}
				}

				var initialized_ = false;
				var model_ = null;
				var mangaMap_ = null;
				var authenticated_ = false;
				var profileName_ = null;
				var profileImage_ = null;

				// Constants for the maps.
				var MANGA = "manga";
				var LATEST_READ = "latestRead";
				var STARRED = "starred";
				var VERSION = "version";
				
				var CLIENT_ID = '423468108258-2i6sdlvnc644qd0nkphhiae2trvaeusb.apps.googleusercontent.com';
				var SCOPES = [
						'https://www.googleapis.com/auth/drive.appfolder',
						'https://www.googleapis.com/auth/plus.me',
				];

				var reauthenticate_ = function() {
						gapi.auth.authorize(
								{
										client_id: CLIENT_ID,
										scope: SCOPES,
										immediate: true
								},
								handleReauthentication_);
				}

				var handleReauthentication_ = function(authResult) {
						if (authResult && !authResult.error) {
								return;
						}
						authenticated_ = false;
						checkAuth_();
				}

				var checkAuth_ = function() {
						if (authenticated_) {
								return;
						}

						gapi.auth.authorize(
								{
										client_id: CLIENT_ID,
										scope: SCOPES,
										immediate: true
								},
								handleAuthResult_);
				}

				var handleAuthResult_ = function(authResult) {
						Promise.resolve().then(function() {
								if (!authResult) {
										return Promise.reject("unknown");
								} else if (authResult.error) {
										return Promise.reject(authResult.error);
								} else {
										loadModel_();
										return gapi.client.plus.people.get({
												'userId' : 'me'
										}).then(function(resp) {
												profileName_ = resp.result.displayName;
												profileImage_ = resp.result.image.url;
										});
								}
						}).then(function () {
								authenticated_ = true;
						}, function(reason) {
								console.log("Auth failed with " + reason);
								authenticated_ = false;
						}).then(function() {
								for (var i = 0; i < instanceKeys_.length; i++) {
										var key = instanceKeys_[i];
										if (instanceMap_.has(key)) {
												instanceMap_.get(key).authenticatedChanged_();
										}
								}
						});
				}

				var initializeModel_ = function(model) {
						var root = model.getRoot();
						root.set(MANGA, model.createMap());
						root.set(VERSION, 2);
				}

				var updateModel_ = function(model) {
						var root = model.getRoot();
						if (root.get(VERSION) == 1) {
								var V1_STARRED = "starred";
								var V1_READ = "read";

								model.beginCompoundOperation("v1to2", false);
								var starredList = root.get(V1_STARRED).asArray();
								var readPairList = root.get(V1_READ).items();

								var mangaMap = model.createMap();
								starredList.forEach(function(value) {
										if (!mangaMap.has(value)) {
												mangaMap.set(value, model.createMap());
										}
										mangaMap.get(value).set(STARRED, true);
								});

								readPairList.forEach(function(pair) {
										var key = pair[0];
										var value = pair[1];
										if (!mangaMap.has(key)) {
												mangaMap.set(key, model.createMap());
										}
										mangaMap.get(key).set(LATEST_READ, value);
								});

								root.set(MANGA, mangaMap);
								root.set(VERSION, 2);
								root.delete(V1_STARRED);
								root.delete(V1_READ);
								model.endCompoundOperation();
								console.log("Updated model from v1 to v2");

								updateModel_(model);
								return;
						}
				}

				var modelLoaded_ = function(doc) {
						model_ = doc.getModel();
						updateModel_(model_);

						var root = model_.getRoot();
						mangaMap_ = root.get(MANGA);

						// TODO: watch version for changes.
						initialized_ = true;
						updateModelReady_();
				}
				
				var modelLoadingFailed_ = function(e) {
						if(e.type == gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {
								reauthenticate_();
						} else if(e.type == gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
								console.error("ERROR: Error loading model: " + e.message);
						} else if(e.type == gapi.drive.realtime.ErrorType.NOT_FOUND) {
								console.error("ERROR: Error loading model: NOT FOUND");
						}
				};

				var loadModel_ = function() {
						gapi.drive.realtime.loadAppDataDocument(modelLoaded_, initializeModel_, modelLoadingFailed_);
				}

				var domReady_ = false;
				var gapiReady_ = false;
				var gapiReadyHandler_ = function() {
						Promise.all([gapi.client.load('plus', 'v1'),
												 gapi.client.load('drive', 'v2')])
								.then(function() {
										gapiReady_ = true;
										if (domReady_ && !authenticated_) {
												checkAuth_();
										}
								});
				}

				gapi.load("auth:client,drive-realtime", gapiReadyHandler_);

				Polymer({
						ready: function() {
								this.modelReady = initialized_;
								if (authenticated_) {
										this.authenticatedChanged_();
								}
						},
						domReady: function() {
								addInstance_(this);
								domReady_ = true;
								if (gapiReady_ && !authenticated_) {
										checkAuth_();
								}
						},
						loggedIn: false,
						modelReady: false,
						profileName: "",
						profileImage: "",
						authenticatedChanged_: function() {
								this.profileName = profileName_;
								this.profileImage = profileImage_;
								this.loggedIn = authenticated_;
						},
						isMangaStarred: function (mangaId) {
								if (!initialized_) {
										return false;
								}

								if (!mangaMap_.has(mangaId)) {
										return false;
								}
								var manga = mangaMap_.get(mangaId);
								return manga.has(STARRED) && manga.get(STARRED);
						},
						setMangaStarred: function (mangaId, starred) {
								if (!initialized_) {
										return false;
								}

								if (!mangaMap_.has(mangaId)) {
										mangaMap_.set(mangaId, model_.createMap());
								}
								mangaMap_.get(mangaId).set(STARRED, starred);
								return true;
						},
						getStarredManga: function() {
								if (!initialized_) {
										return new Set();
								}

								var starredSet = new Set();
								mangaMap_.items().forEach(function(pair) {
										var id = pair[0];
										var manga = pair[1];
										if (manga.has(STARRED) && manga.get(STARRED)) {
												starredSet.add(id);
										}
								});
								return starredSet;
						},
						setLatestReadChapterDate: function (mangaId, chapterDate) {
								if (!initialized_ || this.getLatestReadChapterDate(mangaId) > chapterDate) {
										return;
								}
								if (!mangaMap_.has(mangaId)) {
										mangaMap_.set(mangaId, model_.createMap());
								}
								mangaMap_.get(mangaId).set(LATEST_READ, chapterDate);
						},
						getLatestReadChapterDate: function (mangaId) {
								if (!initialized_ || !mangaMap_.has(mangaId)) {
										return 0;
								}
								var manga = mangaMap.get(mangaId);
								return manga.has(LATEST_READ) ? manga.get(LATEST_READ) : 0;
						},
						getLatestReadChapterDateMap: function() {
								var readMap = new Map();
								if (!initialized_) {
										return readMap;
								}
								mangaMap_.items().forEach(function (pair) {
										var id = pair[0];
										var manga = pair[1];
										if (manga.has(LATEST_READ)) {
												readMap.set(id, manga.get(LATEST_READ));
										}
								});
								return readMap;
						},
						authenticate: function() {
								// Authenticate with a pop-up.
								gapi.auth.authorize(
										{
												client_id: CLIENT_ID,
												scope: SCOPES,
												immediate: false,
										},
										handleAuthResult_);
						},
				});
		})();
	</script>
</polymer-element>
<commit_msg>block forward support<commit_after><link rel="import" href="../bower_components/polymer/polymer.html">
<script type="application/javascript" src="../lib/task.js"></script>
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>

<polymer-element name="gdrive-data" attributes="loggedIn profileName profileImage modelReady">
  <template>

  </template>
	<script>
		(function() {
				var nextInstanceId_ = 0;
				var instanceKeys_ = [];
				var instanceMap_ = new WeakMap();
				var addInstance_ = function (instance) {
						for (var i = 0; i < instanceKeys_.length; i++) {
								if (!instanceMap_.has(instanceKeys_[i])) {
										instanceMap_.set(instanceKeys_[i], instance);
										return;
								}
						}
						var key = {id: nextInstanceId_++};
						instanceKeys_.push(key);
						instanceMap_.set(key, instance);;
				}
				var notifyInstances_ = function (event, msg) {
						for (var i = 0; i < instanceKeys_.length; i++) {
								var key = instanceKeys_[i];
								if (instanceMap_.has(key)) {
										instanceMap_.get(key).fire(event, msg);
								}
						}
				}
				var updateModelReady_ = function () {
						for (var i = 0; i < instanceKeys_.length; i++) {
								var key = instanceKeys_[i];
								if (instanceMap_.has(key)) {
										instanceMap_.get(key).modelReady = initialized_;
								}
						}
				}

				var initialized_ = false;
				var model_ = null;
				var mangaMap_ = null;
				var authenticated_ = false;
				var profileName_ = null;
				var profileImage_ = null;

				// Constants for the maps.
				var MANGA = "manga";
				var LATEST_READ = "latestRead";
				var STARRED = "starred";
				var VERSION = "version";
				
				var CLIENT_ID = '423468108258-2i6sdlvnc644qd0nkphhiae2trvaeusb.apps.googleusercontent.com';
				var SCOPES = [
						'https://www.googleapis.com/auth/drive.appfolder',
						'https://www.googleapis.com/auth/plus.me',
				];

				var reauthenticate_ = function() {
						gapi.auth.authorize(
								{
										client_id: CLIENT_ID,
										scope: SCOPES,
										immediate: true
								},
								handleReauthentication_);
				}

				var handleReauthentication_ = function(authResult) {
						if (authResult && !authResult.error) {
								return;
						}
						authenticated_ = false;
						checkAuth_();
				}

				var checkAuth_ = function() {
						if (authenticated_) {
								return;
						}

						gapi.auth.authorize(
								{
										client_id: CLIENT_ID,
										scope: SCOPES,
										immediate: true
								},
								handleAuthResult_);
				}

				var handleAuthResult_ = function(authResult) {
						Promise.resolve().then(function() {
								if (!authResult) {
										return Promise.reject("unknown");
								} else if (authResult.error) {
										return Promise.reject(authResult.error);
								} else {
										loadModel_();
										return gapi.client.plus.people.get({
												'userId' : 'me'
										}).then(function(resp) {
												profileName_ = resp.result.displayName;
												profileImage_ = resp.result.image.url;
										});
								}
						}).then(function () {
								authenticated_ = true;
						}, function(reason) {
								console.log("Auth failed with " + reason);
								authenticated_ = false;
						}).then(function() {
								for (var i = 0; i < instanceKeys_.length; i++) {
										var key = instanceKeys_[i];
										if (instanceMap_.has(key)) {
												instanceMap_.get(key).authenticatedChanged_();
										}
								}
						});
				}

				var initializeModel_ = function(model) {
						var root = model.getRoot();
						root.set(MANGA, model.createMap());
						root.set(VERSION, 2);
				}

				var updateModel_ = function(model) {
						var root = model.getRoot();
						if (root.get(VERSION) == 1) {
								var V1_STARRED = "starred";
								var V1_READ = "read";

								model.beginCompoundOperation("v1to2", false);
								var starredList = root.get(V1_STARRED).asArray();
								var readPairList = root.get(V1_READ).items();

								var mangaMap = model.createMap();
								starredList.forEach(function(value) {
										if (!mangaMap.has(value)) {
												mangaMap.set(value, model.createMap());
										}
										mangaMap.get(value).set(STARRED, true);
								});

								readPairList.forEach(function(pair) {
										var key = pair[0];
										var value = pair[1];
										if (!mangaMap.has(key)) {
												mangaMap.set(key, model.createMap());
										}
										mangaMap.get(key).set(LATEST_READ, value);
								});

								root.set(MANGA, mangaMap);
								root.set(VERSION, 2);
								root.delete(V1_STARRED);
								root.delete(V1_READ);
								model.endCompoundOperation();
								console.log("Updated model from v1 to v2");

								updateModel_(model);
								return;
						}
				}

				var modelLoaded_ = function(doc) {
						model_ = doc.getModel();
						updateModel_(model_);

						var root = model_.getRoot();

						if (root.get(VERSION) != 2) {
								console.error("Model version " + root.get(VERSION) + " is not supported!");
								return;
						}

						mangaMap_ = root.get(MANGA);

						// TODO: watch version for changes.
						initialized_ = true;
						updateModelReady_();
				}
				
				var modelLoadingFailed_ = function(e) {
						if(e.type == gapi.drive.realtime.ErrorType.TOKEN_REFRESH_REQUIRED) {
								reauthenticate_();
						} else if(e.type == gapi.drive.realtime.ErrorType.CLIENT_ERROR) {
								console.error("ERROR: Error loading model: " + e.message);
						} else if(e.type == gapi.drive.realtime.ErrorType.NOT_FOUND) {
								console.error("ERROR: Error loading model: NOT FOUND");
						}
				};

				var loadModel_ = function() {
						gapi.drive.realtime.loadAppDataDocument(modelLoaded_, initializeModel_, modelLoadingFailed_);
				}

				var domReady_ = false;
				var gapiReady_ = false;
				var gapiReadyHandler_ = function() {
						Promise.all([gapi.client.load('plus', 'v1'),
												 gapi.client.load('drive', 'v2')])
								.then(function() {
										gapiReady_ = true;
										if (domReady_ && !authenticated_) {
												checkAuth_();
										}
								});
				}

				gapi.load("auth:client,drive-realtime", gapiReadyHandler_);

				Polymer({
						ready: function() {
								this.modelReady = initialized_;
								if (authenticated_) {
										this.authenticatedChanged_();
								}
						},
						domReady: function() {
								addInstance_(this);
								domReady_ = true;
								if (gapiReady_ && !authenticated_) {
										checkAuth_();
								}
						},
						loggedIn: false,
						modelReady: false,
						profileName: "",
						profileImage: "",
						authenticatedChanged_: function() {
								this.profileName = profileName_;
								this.profileImage = profileImage_;
								this.loggedIn = authenticated_;
						},
						isMangaStarred: function (mangaId) {
								if (!initialized_) {
										return false;
								}

								if (!mangaMap_.has(mangaId)) {
										return false;
								}
								var manga = mangaMap_.get(mangaId);
								return manga.has(STARRED) && manga.get(STARRED);
						},
						setMangaStarred: function (mangaId, starred) {
								if (!initialized_) {
										return false;
								}

								if (!mangaMap_.has(mangaId)) {
										mangaMap_.set(mangaId, model_.createMap());
								}
								mangaMap_.get(mangaId).set(STARRED, starred);
								return true;
						},
						getStarredManga: function() {
								if (!initialized_) {
										return new Set();
								}

								var starredSet = new Set();
								mangaMap_.items().forEach(function(pair) {
										var id = pair[0];
										var manga = pair[1];
										if (manga.has(STARRED) && manga.get(STARRED)) {
												starredSet.add(id);
										}
								});
								return starredSet;
						},
						setLatestReadChapterDate: function (mangaId, chapterDate) {
								if (!initialized_ || this.getLatestReadChapterDate(mangaId) > chapterDate) {
										return;
								}
								if (!mangaMap_.has(mangaId)) {
										mangaMap_.set(mangaId, model_.createMap());
								}
								mangaMap_.get(mangaId).set(LATEST_READ, chapterDate);
						},
						getLatestReadChapterDate: function (mangaId) {
								if (!initialized_ || !mangaMap_.has(mangaId)) {
										return 0;
								}
								var manga = mangaMap.get(mangaId);
								return manga.has(LATEST_READ) ? manga.get(LATEST_READ) : 0;
						},
						getLatestReadChapterDateMap: function() {
								var readMap = new Map();
								if (!initialized_) {
										return readMap;
								}
								mangaMap_.items().forEach(function (pair) {
										var id = pair[0];
										var manga = pair[1];
										if (manga.has(LATEST_READ)) {
												readMap.set(id, manga.get(LATEST_READ));
										}
								});
								return readMap;
						},
						authenticate: function() {
								// Authenticate with a pop-up.
								gapi.auth.authorize(
										{
												client_id: CLIENT_ID,
												scope: SCOPES,
												immediate: false,
										},
										handleAuthResult_);
						},
				});
		})();
	</script>
</polymer-element>

{'fraction_non_alphanumeric': 0.1299472295514512, 'fraction_numerical': 0.00522207563764292, 'mean_word_length': 1.9967056498105749, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 27, 'https://': 6, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '207525', 'n_tokens_mistral': 9253, 'n_tokens_neox': 5589, 'n_words': 1032}