import axios from 'axios';
import { AsyncStorage } from 'react-native';
import session from './session';
import { Config } from '~/Configuration';
import querystring from 'querystring';
const CancelToken = axios.CancelToken;

export const isCancel = axios.isCancel;

const parseError = err => {
  var message = '';
  if (err.response) {
    switch (err.response.status) {
      case 401:
        message = '로그인 인증이 만료되었습니다.';
        break;
      case 404:
        message = '페이지를 찾을 수 없습니다.';
        break;
      case 400:
        message = '오류가 발생했습니다.';
        break;
      case 500:
        message = '서버오류가 발생했습니다.';
        break;
    }
    const data = err.response.data;
    if (data) {
      if (typeof data === 'string') {
        message = data;
      } else if (typeof data === 'object') {
        if (data.message) {
          message = data.message;
        } else if (data.type && data.traceId) {
          message = data.title;
        } else if (err.response.status == 400) {
          let msg = [];
          for (let key in data) {
            msg.push(data[key]);
          }
          message = msg.join('\n');
        }
      }
    }
    if (message) {
      err._message = err.message;
      err.message = message;
    }
    err.canceled = isCancel(err);

    if (!err.message) {
      err.message = '서버에 연결할 수 없습니다.';
    }
  }

  switch (err.message) {
    case 'Network Error':
      err.message = '네트워크 접속 에러입니다.';
      break;
  }

  return err;
};

const stringify = function(obj, prefix) {
  var str = [],
    p;
  for (p in obj) {
    if (obj.hasOwnProperty(p)) {
      var k = prefix ? prefix + (p.match(/[0-9]+/) ? '[' + p + ']' : '.' + p) : p,
        v = obj[p];
      str.push(v !== null && typeof v === 'object' ? stringify(v, k) : k + '=' + encodeURIComponent(v));
    }
  }
  return str.join('&');
};

// 추후 intercept 로 변경

export const fetchGet = async (url, data, abort = true, timeout = 15000, provideCancel = (cancel) => {}) => {
  let token = '';
  try {
    token = session.getAccessToken();
  } catch(error) {
    console.log('session.getAccessToken error. - ' + error);
  }
  console.log(token);
  
  console.log('Config.BASE_URL', Config.BASE_URL);
  const instance = axios.create({
    baseURL: Config.BASE_URL,
    timeout: timeout,
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  let cancel;

  let [baseurl, query] = url.split('?');
  const querystring = stringify(data);
  if (query) {
    query = `${query}&${querystring}`;
  } else {
    query = querystring;
  }
  if (query) url = `${baseurl}?${query}`;

  console.log(url);

  return new Promise((resolve, reject) => {
    if (abort) {
      if (cancel !== undefined) {
        cancel();
      }
    }

    instance
      .get(url, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
          provideCancel(c);
        }),
      })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(parseError(e));
      });
  });
};

export const fetchPost = async (url, data, headers= {}, abort = true, timeout = 15000, provideCancel = (cancel) => {}) => {
  let token = '';
  try {
    token = session.getAccessToken();
  } catch(error) {
    console.log('session.getAccessToken error. - ' + error);
  }
  console.log(token);

  console.log('Config.BASE_URL', Config.BASE_URL);
  const instance = axios.create({
    baseURL: Config.BASE_URL,
    timeout: timeout,
    headers: {
      Authorization: `Bearer ${token}`,
      ...headers,
    },
  });

  let cancel;

  console.log(url);

  return new Promise((resolve, reject) => {
    if (abort) {
      if (cancel !== undefined) {
        cancel();
      }
    }

    instance
      .post(url, data, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
          provideCancel(c);
        }),
      })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(parseError(e));
      });
  });
};

export const fetchForm = async (url, data, headers= {}, abort = true, timeout = 15000, provideCancel = (cancel) => {}) => {
  let token = '';
  try {
    token = session.getAccessToken();
  } catch(error) {
    console.log('session.getAccessToken error. - ' + error);
  }
  console.log(token);

  console.log('Config.BASE_URL', Config.BASE_URL);
  const instance = axios.create({
    baseURL: Config.BASE_URL,
    timeout: timeout,
    headers: {
      Authorization: `Bearer ${token}`,
      ...headers,
    },
  });

  let cancel;

  console.log(url);

  return new Promise((resolve, reject) => {
    if (abort) {
      if (cancel !== undefined) {
        cancel();
      }
    }

    if (typeof data == 'object') {
      data = querystring.stringify(data);
    }

    instance
      .post(url, data, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
          provideCancel(c);
        }),
      })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(parseError(e));
      });
  });
};

export const fetchPut = async (url, data, abort = true, timeout = 15000) => {
  let token = '';
  try {
    token = session.getAccessToken();
  } catch(error) {
    console.log('session.getAccessToken error. - ' + error);
  }
  console.log(token);

  const instance = axios.create({
    baseURL: Config.BASE_URL,
    timeout: timeout,
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  let cancel;

  console.log(url);

  return new Promise((resolve, reject) => {
    if (abort) {
      if (cancel !== undefined) {
        cancel();
      }
    }

    instance
      .put(url, data, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
        }),
      })
      .then(res => {
        resolve(res.data);
      })
      .catch(e => {
        reject(parseError(e));
      });
  });
};

export default fetchGet;


export const fetchDelete = (url, data, abort = true, timeout = 15000) => {
  let token = '';
  try {
    token = session.getAccessToken();
  } catch(error) {
    console.log('session.getAccessToken error. - ' + error);
  }
  console.log(token);

  const instance = axios.create({
    baseURL: Config.BASE_URL,
    timeout: timeout,
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  console.log(url);
  let cancel;

  return new Promise((resolve, reject) => {
    if (abort) {
      if (cancel !== undefined) {
        cancel();
      }
    }

    instance
      .delete(url, data, {
        cancelToken: new CancelToken(function executor(c) {
          cancel = c;
        }),
      })
      .then(res => {
        resolve(res);
      })
      .catch(e => {
        reject(parseError(e));
      });
  });
};
