import {makeT} from 'app/client/lib/localization';
import {AppModel} from 'app/client/models/AppModel';
import {TelemetryModel, TelemetryModelImpl} from 'app/client/models/TelemetryModel';
import {basicButtonLink, bigBasicButton, bigBasicButtonLink, bigPrimaryButton} from 'app/client/ui2018/buttons';
import {theme} from 'app/client/ui2018/cssVars';
import {icon} from 'app/client/ui2018/icons';
import {cssLink} from 'app/client/ui2018/links';
import {loadingSpinner} from 'app/client/ui2018/loaders';
import {commonUrls} from 'app/common/gristUrls';
import {TelemetryPrefsWithSources} from 'app/common/InstallAPI';
import {Computed, Disposable, dom, makeTestId, styled} from 'grainjs';

const testId = makeTestId('test-support-grist-page-');

const t = makeT('SupportGristPage');

export class SupportGristPage extends Disposable {
  private readonly _model: TelemetryModel = new TelemetryModelImpl(this._appModel);
  private readonly _optInToTelemetry = Computed.create(this, this._model.prefs,
    (_use, prefs) => {
      if (!prefs) { return null; }

      return prefs.telemetryLevel.value !== 'off';
    })
    .onWrite(async (optIn) => {
      const telemetryLevel = optIn ? 'limited' : 'off';
      await this._model.updateTelemetryPrefs({telemetryLevel});
    });

  constructor(private _appModel: AppModel) {
    super();
    this._model.fetchTelemetryPrefs().catch(reportError);
  }

  public buildTelemetrySection() {
    return cssSection(
      dom.domComputed(this._model.prefs, prefs => {
        if (prefs === null) {
          return cssSpinnerBox(loadingSpinner());
        }

        if (!this._appModel.isInstallAdmin()) {
          // TODO: We are no longer serving this page to non-admin users, so this branch should no
          // longer match, and this version perhaps should be removed.
          if (prefs.telemetryLevel.value === 'limited') {
            return [
              cssParagraph(t(
                'This instance is opted in to telemetry. Only the site administrator has permission to change this.',
              ))
            ];
          } else {
            return [
              cssParagraph(t(
                'This instance is opted out of telemetry. Only the site administrator has permission to change this.',
              ))
            ];
          }
        } else {
          return [
            cssParagraph(t(
              'Support Grist by opting in to telemetry, which helps us understand how the product ' +
              'is used, so that we can prioritize future improvements.'
            )),
            cssParagraph(
              t('We only collect usage statistics, as detailed in our {{link}}, never document contents.', {
                link: telemetryHelpCenterLink(),
              }),
            ),
            cssParagraph(t('You can opt out of telemetry at any time from this page.')),
            this._buildTelemetrySectionButtons(prefs),
          ];
        }
      }),
      testId('telemetry-section'),
    );
  }

  public getTelemetryOptInObservable() { return this._optInToTelemetry; }

  public _buildTelemetrySectionButtons(prefs: TelemetryPrefsWithSources) {
    const {telemetryLevel: {value, source}} = prefs;
    if (source === 'preferences') {
      return dom.domComputed(this._optInToTelemetry, (optedIn) => {
        if (optedIn) {
          return [
            cssOptInOutMessage(
              t('You have opted in to telemetry. Thank you!'), ' 🙏',
              testId('telemetry-section-message'),
            ),
            cssOptOutButton(t('Opt out of Telemetry'),
              dom.on('click', () => this._optInToTelemetry.set(false)),
            ),
          ];
        } else {
          return [
            cssOptInButton(t('Opt in to Telemetry'),
              dom.on('click', () => this._optInToTelemetry.set(true)),
            ),
          ];
        }
      });
    } else {
      return cssOptInOutMessage(
        value !== 'off'
          ? [t('You have opted in to telemetry. Thank you!'), ' 🙏']
          : t('You have opted out of telemetry.'),
        testId('telemetry-section-message'),
      );
    }
  }

  public buildSponsorshipSection() {
    return cssSection(
      cssParagraph(
        t(
          'Grist software is developed by Grist Labs, which offers free and paid ' +
          'hosted plans. We also make Grist code available under a standard free ' +
          'and open OSS license (Apache 2.0) on {{link}}.',
          {link: gristCoreLink()},
        ),
      ),
      cssParagraph(
        t(
          'You can support Grist open-source development by sponsoring ' +
          'us on our {{link}}.',
          {link: sponsorGristLink()},
        ),
      ),
      cssParagraph(t(
        'We are a small and determined team. Your support matters a lot to us. ' +
        'It also shows to others that there is a determined community behind this product.'
      )),
      cssSponsorButton(
        cssButtonIconAndText(icon('Heart'), cssButtonText(t('Manage Sponsorship'))),
        {href: commonUrls.githubSponsorGristLabs, target: '_blank'},
      ),
      testId('sponsorship-section'),
    );
  }

  public buildSponsorshipSmallButton() {
    return basicButtonLink('💛 ', t('Sponsor'),
      {href: commonUrls.githubSponsorGristLabs, target: '_blank'});
  }
}

function telemetryHelpCenterLink() {
  return cssLink(
    t('Help Center'),
    {href: commonUrls.helpTelemetryLimited, target: '_blank'},
  );
}

function sponsorGristLink() {
  return cssLink(
    t('GitHub Sponsors page'),
    {href: commonUrls.githubSponsorGristLabs, target: '_blank'},
  );
}

function gristCoreLink() {
  return cssLink(
    t('GitHub'),
    {href: commonUrls.githubGristCore, target: '_blank'},
  );
}

const cssSection = styled('div', ``);

const cssParagraph = styled('div', `
  color: ${theme.text};
  font-size: 14px;
  line-height: 20px;
  margin-bottom: 12px;
`);

const cssOptInOutMessage = styled(cssParagraph, `
  line-height: 40px;
  font-weight: 600;
  margin-top: 24px;
  margin-bottom: 0px;
`);

const cssOptInButton = styled(bigPrimaryButton, `
  margin-top: 24px;
`);

const cssOptOutButton = styled(bigBasicButton, `
  margin-top: 24px;
`);

const cssSponsorButton = styled(bigBasicButtonLink, `
  margin-top: 24px;
`);

const cssButtonIconAndText = styled('div', `
  display: flex;
  align-items: center;
`);

const cssButtonText = styled('span', `
  margin-left: 8px;
`);

const cssSpinnerBox = styled('div', `
  margin-top: 24px;
  text-align: center;
`);