#include<bits/stdc++.h>

using namespace std;

int ans, CNT, N, pos[200009], A[200009], pf[200009], sf[200009], toDel[200009], toAdd[200009];
const int mod = 1e9 + 7;
pair < int, int > v[200009];

int add (int x, int y) {int ans = x + y; if (ans >= mod) ans -= mod; return ans;}
int subtract (int x, int y) {if (x >= y) return x - y; return x - y + mod;}
int mul (int x, int y) {return 1LL * x * y % mod;}
void adto (int &x, int y) {x += y; if (x >= mod) x -= mod;}

int power (int a, int b)
{
    int p = 1;
    for (int i=0; (1<<i) <= b; i++)
    {
        if (b & (1 << i)) p = mul (p, a);
        a = mul (a, a);
    }
    return p;
}

/*void Prec (int lim){fac[0] = inv[0] = 1;for (int i=1; i<=lim; i++)fac[i] = mul (fac[i - 1], i);
inv[lim] = power (fac[lim], mod - 2);for (int i=lim - 1; i>=0; i--)inv[i] = mul (inv[i + 1], i + 1);}
int comb (int N, int K){int ans = mul (fac[N], inv[N - K]);ans = mul (ans, inv[K]);return ans;}*/

namespace segtree {
    int ans = 0, aint[800008], lzy[800008];
    void split (int nod, int st, int dr)
    {
        int f1 = nod << 1, f2 = f1 | 1;
        if (lzy[nod] == 1) return ;
        aint[f1] = mul (aint[f1], lzy[nod]);
        aint[f2] = mul (aint[f2], lzy[nod]);
        lzy[f1] = mul (lzy[f1], lzy[nod]);
        lzy[f2] = mul (lzy[f2], lzy[nod]);
        lzy[nod] = 1;
    }

    void Build (int nod, int st, int dr)
    {
        lzy[nod] = 1, aint[nod] = 0;
        if (st == dr) return ;
        int mij = (st + dr) >> 1, f1 = nod << 1, f2 = f1 | 1;
        Build (f1, st, mij);
        Build (f2, mij + 1, dr);
        aint[nod] = add (aint[f1], aint[f2]);
    }

    void Update (int nod, int st, int dr, int pos, int val)
    {
        if (st == dr)
        {
            aint[nod] = val;
            return ;
        }
        int mij = (st + dr) >> 1, f1 = nod << 1, f2 = f1 | 1;
        split (nod, st, dr);
        if (pos <= mij) Update (f1, st, mij, pos, val);
        else Update (f2, mij + 1, dr, pos, val);
        aint[nod] = add (aint[f1], aint[f2]);
    }

    void UpdateSegm (int nod, int st, int dr, int x, int y, int val)
    {
        if (x <= st && dr <= y)
        {
            lzy[nod] = mul (lzy[nod], val);
            aint[nod] = mul (aint[nod], val);
            return ;
        }
        int mij = (st + dr) >> 1, f1 = nod << 1, f2 = f1 | 1;
        split (nod, st, dr);
        if (x <= mij) UpdateSegm (f1, st, mij, x, y, val);
        if (mij < y) UpdateSegm (f2, mij + 1, dr, x, y, val);
        aint[nod] = add (aint[f1], aint[f2]);
    }

    void Query (int nod, int st, int dr, int x, int y)
    {
        if (x <= st && dr <= y)
        {
            if (x == st) ans = aint[nod];
            else adto (ans, aint[nod]);
            return ;
        }
        int mij = (st + dr) >> 1, f1 = nod << 1, f2 = f1 | 1;
        split (nod, st, dr);
        if (x <= mij) Query (f1, st, mij, x, y);
        if (mij < y) Query (f2, mij + 1, dr, x, y);
    }

    int Query (int l, int r)
    {
        Query (1, 1, N, l, r);
        return ans;
    }
}

int main ()
{
//freopen ("input", "r", stdin);
//freopen ("output", "w", stdout);

scanf ("%d", &N);
for (int i=1; i<=N; i++)
    scanf ("%d", &v[i].first), v[i].second = i;
sort (v + 1, v + N + 1);
for (int i=1; i<=N; i++)
    A[i] = v[i].first, pos[i] = v[i].second;
/*for (int i=1; i<=N; i++)
    printf ("%d %d\n", A[i], pos[i]);*/
pf[0] = 1;
for (int i=1; i<=N; i++)
{
    if (A[i] <= i - 1)
    {
        printf ("0\n");
        return 0;
    }
    pf[i] = mul (pf[i - 1], A[i] - (i - 1));
    toAdd[i] = (1LL * (A[i] - (i - 1)) * (A[i] - i) / 2) % mod;
}
CNT = pf[N];
sf[N + 1] = 1;
for (int i=N; i>=1; i--)
{
    sf[i] = mul (sf[i + 1], A[i] - i + 1);
    toDel[i] = power (A[i] - i, mod - 2);
}
int lzy = 1;
segtree::Build (1, 1, N);
for (int i=N; i>=1; i--)
{
    int curr = segtree::Query (pos[i], N);
    curr = mul (curr, pf[i - 1]);
    curr = mul (curr, toAdd[i]);
    adto (ans, curr);
    segtree::lzy[1] = mul (segtree::lzy[1], A[i] - i);
    segtree::Update (1, 1, N, pos[i], sf[i + 1]);
}
segtree::Build (1, 1, N), lzy = 1;
for (int i=N; i>=1; i--)
{
    int curr = segtree::Query (1, pos[i]);
    curr = mul (curr, pf[i - 1]);
    curr = mul (curr, toAdd[i]);
    ans = subtract (ans, curr);
    segtree::lzy[1] = mul (segtree::lzy[1], A[i] - i);
    segtree::Update (1, 1, N, pos[i], sf[i + 1]);
}
segtree::Build (1, 1, N), lzy = 1;
for (int i=N; i>=1; i--)
{
    int curr = segtree::Query (1, pos[i]);
    curr = mul (curr, CNT);
    adto (ans, curr);
    segtree::Update (1, 1, N, pos[i], 1);
}
/*for (int i=1; i<=N; i++)
    for (int j=i + 1; j<=N; j++)
    {
        int curr = mul (pf[i - 1], toAdd[i]);
        for (int k=i + 1; k<=N; k++)
            if (k < j)
                curr = mul (curr, A[k] - k);
            else
            if (k > j)
                curr = mul (curr, A[k] - (k - 1));
        if (pos[j] > pos[i]) adto (ans, curr);
        else adto (ans, subtract (CNT, curr));
    }*/
printf ("%d\n", ans);
return 0;
}


Measured memory_bytes: 12800