
const gameBar = (function(win, doc, navi, Vue, vault, gameStrings) {
  ;
  
  const icons = {
    fruit: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 176C311.2 176 304 168.8 304 160L304 144C304 99.8 339.8 64 384 64L400 64C408.8 64 416 71.2 416 80L416 96C416 140.2 380.2 176 336 176L320 176zM96 352C96 275.7 131.7 192 208 192C235.3 192 267.7 202.3 290.7 211.3C309.5 218.6 330.6 218.6 349.4 211.3C372.3 202.4 404.8 192 432.1 192C508.4 192 544.1 275.7 544.1 352C544.1 480 464.1 576 384.1 576C367.6 576 346 569.4 332.6 564.7C324.5 561.9 315.7 561.9 307.6 564.7C294.2 569.4 272.6 576 256.1 576C176.1 576 96.1 480 96.1 352z"/></svg>',
    server: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M160 96C124.7 96 96 124.7 96 160L96 224C96 259.3 124.7 288 160 288L480 288C515.3 288 544 259.3 544 224L544 160C544 124.7 515.3 96 480 96L160 96zM376 168C389.3 168 400 178.7 400 192C400 205.3 389.3 216 376 216C362.7 216 352 205.3 352 192C352 178.7 362.7 168 376 168zM432 192C432 178.7 442.7 168 456 168C469.3 168 480 178.7 480 192C480 205.3 469.3 216 456 216C442.7 216 432 205.3 432 192zM160 352C124.7 352 96 380.7 96 416L96 480C96 515.3 124.7 544 160 544L480 544C515.3 544 544 515.3 544 480L544 416C544 380.7 515.3 352 480 352L160 352zM376 424C389.3 424 400 434.7 400 448C400 461.3 389.3 472 376 472C362.7 472 352 461.3 352 448C352 434.7 362.7 424 376 424zM432 448C432 434.7 442.7 424 456 424C469.3 424 480 434.7 480 448C480 461.3 469.3 472 456 472C442.7 472 432 461.3 432 448z"/></svg>',
    x: '<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M160 96C124.7 96 96 124.7 96 160L96 480C96 515.3 124.7 544 160 544L480 544C515.3 544 544 515.3 544 480L544 160C544 124.7 515.3 96 480 96L160 96zM457.1 180L353.3 298.6L475.4 460L379.8 460L305 362.1L219.3 460L171.8 460L282.8 333.1L165.7 180L263.7 180L331.4 269.5L409.6 180L457.1 180zM419.3 431.6L249.4 206.9L221.1 206.9L392.9 431.6L419.3 431.6z"/></svg>',
    google: '<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M564 325.8C564 467.3 467.1 568 324 568C186.8 568 76 457.2 76 320C76 182.8 186.8 72 324 72C390.8 72 447 96.5 490.3 136.9L422.8 201.8C334.5 116.6 170.3 180.6 170.3 320C170.3 406.5 239.4 476.6 324 476.6C422.2 476.6 459 406.2 464.8 369.7L324 369.7L324 284.4L560.1 284.4C562.4 297.1 564 309.3 564 325.8z"/></svg>'
  };
  const { createApp } = Vue,
  userDefaults = {
      score: 0,
      current_model: 'cat',
      collected_fruits: [],
      email: ''
    },
    lang = {
      available: {
        en: 'English',
        es: 'Spanish',
      },
      default: 'es',
      browser: navi.language.substring(0, 2),
    },
    API_URL = 'https://ws.devignia.site/api',
    WS_URL = 'https://ws.devignia.site';
  
  const gameBar = createApp({
    data: () => ({
      lang: lang.available.hasOwnProperty(lang.browser) ? lang.browser : lang.default,
      msgs: [],
      points: 0,
      fruitsFound: 0,
      currentModel: '',
      loggerInterval: false,
      bouncyText: false,
      online: navi.onLine, // Reference to `navigator.onLine`
      isLoggedIn: false,
      providerLogin: {
        x: WS_URL + '/auth/x/login',
        google: WS_URL + '/auth/google/login',
      },
      labels: {
        fruitsFound: ``,
        serverStatus: ``,
      },
      hints: {
        email: false,
        password: false,
      },
      modals: {
        about: {
          isOpen: false
        }
      },
      buttons: {
        install: {
          hidden: false
        }
      },
      user: userDefaults,
      form: {
        status: 'default',
        user: {
          username: '',
          password: '',
        },
        disabled: false
      },
      forms: {
        user: {
          status: 'default',
          disabled: false
        }
      },
      ui: {
        tabs: {
          current: 'account'
        },
        auth: {
          step: 1,
          register: true
        },
		hints: {
			requires_completion: false
		},
        icons
      },
      vault: {}
    }),
    methods: {
      accountExists() {
        (async () => {
          const url = API_URL + '/account/exists';
          const method = 'POST';
          
          let body = new FormData();
          body.append('email', this.form.user.username);
          
          this.form.status = 'loading';
          
          try {
            const res = await fetch(url, { method, body });
            
            if (!res.ok)
              throw new Error('Error when requesting resource: ' + res.status);
            
            const bd = await res.json();
            this.form.status = 'success';
            this.ui.auth.step = 2;
            this.ui.auth.register = !bd.exists;
            
          } catch (e) {
            this.form.status = 'error';
          }
        })();
      },
      authStart() {
        this.ui.auth.step = 1;
        this.resetForm();
      },
      authContinue(ev) {
        
        (async () => {
          let url, data;
          if (this.ui.auth.register) {
            url = WS_URL + '/register';
            // API Form Data
            data = {
              name: this.form.user.name,
              email: this.form.user.username,
              password: this.form.user.password,
              password_confirmation: this.form.user.password_confirmation,
              current_character: this.vault.get('current') || 'cat',
              score: this.vault.get('points'),
              browser_uuid: this.vault.get('userId')
            };
          } else {
            url = WS_URL + '/login';
            // API Form Data
            data = {
              email: this.form.user.username,
              password: this.form.user.password,
              current_character: this.vault.get('current') || 'cat',
              score: this.vault.get('points'),
              browser_uuid: this.vault.get('userId')
            };
          };
          
          const method = 'POST';
          const body = new FormData();
          const headers = new Headers();
          headers.append('x-csrf-token', this.vault.get('csrf-token'));
          for (let d in data)
            body.append(d, data[d]);
          
          this.form.disabled = true;
          this.form.status = 'loading';
          
          try {
            const res = await fetch(url, {
              method,
              body,
              headers
            });
            
            if (!res.ok)
              throw new Error('Error when requesting resource: ' + res.status);
            
            const bd = await res.json();
            
            this.form.status = 'success';
            this.updateUser(bd.data.user);
            
            this.vault.save('username', this.user.email);
            this.vault.save('userId', this.user.browser_uuid);
            this.vault.save('user', this.user);
            this.vault.save('token', this.user.token);
            this.setPoints(bd.data.user.score);
            this.isLoggedIn = true;
            setTimeout(() => {
              this.resetForm();
            }, 2500);
            
          } catch (e) {
            
            this.form.disabled = false;
            this.form.status = 'error';
            console.log(e.message)
          };
        })();
        
      },
      installPwa() {},
      setLabels(which = false) {
        
        if (which == 'fruits' || !which)
          this.labels.fruitsFound = `${this.fruitsFound} ${icons.fruit}<small class="d-block d-sm-inline-block mt-1">${this.t9('Fruits')}</small>`;
        
        if (which == 'server' || !which)
          this.labels.serverStatus = `${icons.server}<small class="d-block d-sm-inline-block mt-1">${this.online ? 'Online' : 'Offline'}</small>`;
      },
      t9(key) {
        return gameStrings[this.lang] ? (gameStrings[this.lang][key] || key) : key
      },
      setScore(points) {
        this.setPoints(points)
      },
      setPoints(points) {
        this.points = points;
        this.bouncyText = true;
        setTimeout(function() {
          gameBar.bouncyText = false;
        }, 500);
      },
      updateUser(user) {
        for (let u in user)
          this.user[u] = user[u];
      },
      updateProfile() {
        (async () => {
          const body = new FormData();
          const url = API_URL + '/user/profile';
          const method = 'POST';
          const profileImage = doc.querySelector('#profile-image').files[0];
          let user = vault.get('user');
          const headers = new Headers({
            'Authorization': 'Bearer ' + this.vault.get('token')
          });
          body.append('name', this.user.name);
		  if(this.user.password != '' && this.user.password_confirmation != '') {
			  body.append('password', this.user.password);
			  body.append('password_confirmation', this.user.password_confirmation);
		  }
          body.append('id', user.id);
          body.append('browser_uuid', user.browser_uuid);
          if (profileImage != undefined)
            body.append('profile_image', profileImage);
          this.forms.user.status = 'loading';
          this.forms.user.disabled = true;
          try {
            const res = await fetch(url, { method, body, headers });
            if (!res.ok)
              throw new Error('Error when requesting resource: ' + res.status);
            const bd = await res.json();
            vault.save('user', bd.data.user);
            this.updateUser(bd.data.user);
			this.ui.hints.requires_completion = bd.data.user.requires_completion;
            this.forms.user.status = 'success';
            this.forms.user.disabled = false;
          } catch (e) {
            this.forms.user.status = 'error';
            this.forms.user.disabled = false;
            console.log(e.message);
          };
          
        })();
      },
      resetForm() {
        this.form.user = {
          username: '',
          password: '',
        };
        this.form.status = 'default';
        this.form.disabled = false;
      },
      resetUser() {
        this.updateUser(userDefaults);
      },
      setOnline() {
        this.online = navigator.onLine;
      },
      logout() {
        this.resetUser();
        this.vault.reset();
        this.isLoggedIn = false;
        this.setPoints(0);
        this.vault.save('current', 'cat');
        this.authStart();
      },
      setInstructions() {
        const className = 'text-large';
        const instructions = [
          i18nfp.gettext("🤳 Look around with your device to find fruits."),
          i18nfp.gettext("Tap a fruit 👆 to feed the cat."),
        ].forEach((msg, key) => {
          setTimeout(function() {}, INSTRUCTIONS_TIMEOUT * (key + 2));
        });
        
        setTimeout(function() {}, 30000);
      },
      noopLogin(user) {
        (async () => {
          const url = API_URL + '/auth';
          const method = 'POST';
          const body = new FormData();
          body.append('id', user.id);
          body.append('browser_uuid', user.browser_uuid);
          try {
            const res = await fetch(url, { method, body });
            if (!res.ok)
              throw new Error('Error when requesting resource: ' + res.status);
            const bd = await res.json();
          } catch (e) {
            console.log(e);
          };
        })();
      },
      log(msg, className) {
		  return msg;
		  /*
		  @todo
        this.msgs.push({ msg, className });
        // Every time a log is added, schedule its removal
        setTimeout(function() {
          gameBar.msgs.splice(0, 1);
        }, POP_TIME);
		*/
      },
      fetchCsrfToken() {
        // CSRF Token
        (async () => {
          try {
            const res = await fetch(WS_URL + '/csrf-token');
            if (!res.ok)
              throw new Error('Error when requesting resource: ' + res.status);
            
            const body = await res.json();
            
            
            
            this.vault.save('csrf-token', body.csrf_token);
          } catch (e) { console.log(e.message) }
        })();
        
      },
	   tokenLogin(token, callback) {
   
			(async () => {
			  const method = 'POST';
			  const headers = new Headers();
			  headers.append('Authorization', 'Bearer ' + token);
			  
			  const res = await fetch(API_URL + '/user', { headers });
			  if(!res.ok)
				  throw new Error('Error logging in with sanctum token');
			  
			  const bd = await res.json();
			  this.updateUser(bd.data.user);
			  this.vault.save('user', bd.data.user);
			  this.ui.hints.requires_completion = bd.data.user.requires_completion;
			  return callback();
			})();
		  }
    },
    watch: {
      points() {},
      fruitsFound() {
        this.setLabels('fruits');
      },
      online() {
        this.setLabels('server');
      },
      'user.email'(m) {
        this.isLoggedIn = (m != '')
      }
    },
    mounted() {
      
      // this.labels.score = vault.get('points', 0) + ' <small>pts</small>';
      
      //this.log(this.lang.ngettext("Let's go Fruit Picking!"));
      //this.setInstructions();
      this.fetchCsrfToken();
    },
    
    created() {
      //this.lang = i18nfp;
      this.vault = vault.init('fruitpick');
      this.user.email = this.vault.get('username');
      this.updateUser(this.vault.get('user'));
      this.setPoints(this.vault.get('points', 0));
      this.currentModel = this.vault.get('current');
      this.setLabels();
      this.ui.hints.requires_completion = this.user.requires_completion;
      // Detect if app is coming from a provider oauth flo
      if (win.location.hash != '') {
        let params = new URLSearchParams(
                win.location.hash.split('?')[1]
            );
        
        const token = params.get('auth');
        if (token != null) {
          this.vault.save('token', token);
		  this.tokenLogin(token, function() {
			  win.history.pushState({ token: token }, '', '/fruitpick')
		  });
          
        }
      }
    },
  }).mount('.game-bar');
  
  
  win.addEventListener('online', function() { gameBar.setOnline() });
  win.addEventListener('offline', function() { gameBar.setOnline() });
  
  return gameBar;
  
})(window, document, navigator, Vue, Vault, gameStrings);

// GameBar Vue Component
